stringtranslate.com

оценивать

В некоторых языках программирования , evalсокращение от английского Assessment, — это функция , которая оценивает строку, как если бы она была выражением на языке, и возвращает результат ; в других случаях он выполняет несколько строк кода, как если бы они были включены вместо строки, включающей eval. Входные данные evalне обязательно являются строкой; это может быть структурированное представление кода, такое как абстрактное синтаксическое дерево (например, формы Lisp ), или представление специального типа, например code(как в Python). Аналогом оператора является exec , который выполняет строку (или код в другом формате), как если бы это был оператор; в некоторых языках, таких как Python, присутствуют оба, тогда как в других языках присутствует только один из них evalили exec.

Риски безопасности

Использование evalданных из ненадежного источника может привести к уязвимостям безопасности. Например, если предположить, что get_data()функция получает данные из Интернета, этот код Python небезопасен:

сеанс [ 'аутентифицированный' ]  =  Ложные данные  =  get_data () foo  =  eval ( данные )

Злоумышленник может предоставить программе строку "session.update(authenticated=True)"в качестве данных, которая обновит sessionсловарь, чтобы установить для аутентифицированного ключа значение True. Чтобы исправить это, все данные, которые будут использоваться, evalдолжны быть экранированы или запускаться без доступа к потенциально опасным функциям.

Выполнение

В интерпретируемых языках почти evalвсегда реализуется с помощью того же интерпретатора, что и обычный код. В компилируемых языках тот же компилятор, который используется для компиляции программ, может быть встроен в программы, использующие эту evalфункцию; иногда используются отдельные интерпретаторы, однако это приводит к дублированию кода .

Языки программирования

ECMAScript

JavaScript

В JavaScript это evalчто-то вроде гибрида оценщика выражений и исполнителя операторов. Он возвращает результат последнего вычисленного выражения.

Пример в качестве средства оценки выражений:

Фу = 2 ; предупреждение ( eval ( 'foo + 2' ));  

Пример в качестве исполнителя оператора:

Фу = 2 ; eval ( 'foo = foo + 2;alert(foo);' );  

Одним из применений JavaScript evalявляется анализ текста JSON , возможно, как часть инфраструктуры Ajax . Однако современные браузеры предоставляют JSON.parseболее безопасную альтернативу этой задаче.

ActionScript

В ActionScript (языке программирования Flash) evalнельзя использовать для вычисления произвольных выражений. Согласно документации Flash 8, его использование ограничено выражениями, которые представляют собой «имя переменной, свойства, объекта или фрагмента ролика, который необходимо получить. Этот параметр может быть либо строкой, либо прямой ссылкой на экземпляр объекта». [1]

ActionScript 3 не поддерживает eval.

Библиотека ActionScript 3 Eval [2] и D.eval API [3] были проектами разработки, целью которых было создание эквивалентов evalActionScript 3. Оба проекта завершились, поскольку срок службы Adobe Flash Player подошел к концу .

Лисп

Лисп был первым языком, в котором использовалась evalфункция в 1958 году. Фактически, определение функции evalпривело к первой реализации языкового интерпретатора. [4] До того, как evalфункция была определена, функции Lisp вручную компилировались в операторы языка ассемблера . Однако после того, как evalфункция была скомпилирована вручную, она затем использовалась как часть простого цикла чтения-оценки-печати , который лег в основу первого интерпретатора Лиспа.

Более поздние версии функций Lisp evalтакже были реализованы в виде компиляторов.

Функция evalв Лиспе ожидает, что форма будет оценена как ее аргумент. Результирующее значение данной формы будет возвращаемым значением вызова eval.

Это пример кода на Лиспе:

; Форма, вызывающая функцию + с числами 1,2 и 3 в качестве аргументов. ; Он возвращает 6. ( + 1 2 3 ) ; В Лиспе любая форма предназначена для оценки, поэтому ; был выполнен вызов +. ; Мы можем запретить Lisp выполнять оценку ; формы, добавив к ней префикс «'», например: ( setq form1 ' ( + 1 2 3 ) ) ; Теперь form1 содержит форму, которую может использовать eval, для ; пример: ( eval form1 ) ; eval вычислил (+ 1 2 3) и вернул 6.         

Известно, что Лисп очень гибок, как и его evalфункции. Например, чтобы оценить содержимое строки, ее сначала необходимо преобразовать в форму Lisp с помощью функции read-from-string, а затем полученную форму необходимо передать eval:

( eval ( read-from-string "(format t \"Hello World!!!~%\")" ))  

Одним из основных вопросов, вызывающих путаницу, является вопрос, в каком контексте будут оцениваться символы в форме. В приведенном выше примере form1содержит символ +. Оценка этого символа должна дать функцию для сложения, чтобы пример работал так, как задумано. Таким образом, некоторые диалекты Лиспа допускают дополнительный параметр для evalуказания контекста вычисления (аналогично необязательным аргументам evalфункции Python — см. ниже). Пример на диалекте Scheme Lisp (R 5 RS и более поздние версии):

;; Определите некоторую простую форму, как в приведенном выше примере. ( define form2 ' ( + 5 2 )) ;Значение: form2    ;; Оцените форму в исходном контексте. ;; Контекст для оценки на сленге Scheme называется «средой». ( eval form2 пользовательская начальная среда ) ; Значение: 7  ;; Запутайте исходное окружение, чтобы + было ;; имя функции вычитания. ( environment-define user-initial-environment '+ - ) ;Значение: +   ;; Оцените форму еще раз. ;; Обратите внимание, что возвращаемое значение изменилось. ( eval form2 пользовательская начальная среда ) ; Значение: 3  

Перл

В Perl эта evalфункция представляет собой нечто вроде гибрида средства оценки выражений и исполнителя операторов. Он возвращает результат последнего вычисленного выражения (все операторы являются выражениями в программировании на Perl) и позволяет опустить последнюю точку с запятой.

Пример в качестве средства оценки выражений:

$фу = 2 ; print eval ( '$foo + 2' ), "\n" ;    

Пример в качестве исполнителя оператора:

$фу = 2 ; eval ( '$foo += 2; print "$foo\n";' );  

В Perl также есть eval блоки , которые служат механизмом обработки исключений (см. Синтаксис обработки исключений#Perl ). Это отличается от описанного выше использования evalсо строками тем, что код внутри evalблоков интерпретируется во время компиляции, а не во время выполнения, поэтому это не является смыслом evalиспользования в этой статье.

PHP

В PHP выполняет evalкод в строке почти так же, как если бы он был помещен в файл вместо вызова eval(). Единственным исключением является то, что ошибки сообщаются как возникшие в результате вызова eval(), а операторы возврата становятся результатом функции.

В отличие от некоторых языков, аргумент evalдолжен быть строкой из одного или нескольких полных операторов, а не только выражений; однако можно получить форму «выражения», evalпоместив выражение в оператор возврата, что приводит evalк возврату результата этого выражения.

В отличие от некоторых языков, PHP evalявляется «языковой конструкцией», а не функцией [5] , и поэтому не может использоваться в некоторых контекстах, где могут быть функции, например функции более высокого порядка.

Пример использования эха:

<?php $foo  =  "Привет, мир! \n " ; eval ( 'echo "$foo";' ); ?>

Пример возврата значения:

<?php $foo  =  "Прощай, мир! \n " ;  // не работает в PHP5 echo  eval ( 'return $foo;' ); ?>

Луа

В Lua 5.1 loadstringкомпилирует код Lua в анонимную функцию.

Пример в качестве средства оценки выражений:

loadstring ( "print('Hello World!')" )()

Пример выполнения оценки в два этапа:

a  =  1 f  =  loadstring ( «return a + 1» )  — скомпилируйте выражение в анонимную функцию print ( f ())  — выполните (и напечатайте результат «2»)

Lua 5.2 устарел loadstringв пользу существующей loadфункции, которая была расширена для приема строк. Кроме того, это позволяет напрямую предоставлять среду функции, поскольку среды теперь являются upvalues .

load ( "print('Hello ' .. a)" ,  "" ,  "t" ,  {  a  =  "World!" ,  print  =  print  })()

Постскриптум

Оператор PostScript принимаетexec операнд — если это простой литерал, он помещает его обратно в стек. Однако если взять строку, содержащую выражение PostScript, можно преобразовать строку в исполняемый файл, который затем может быть выполнен интерпретатором, например:

 ((Привет, мир) =) cvx exec  

преобразует выражение PostScript

 (Привет, мир) = 

который извлекает строку «Hello World» из стека и отображает ее на экране, чтобы она имела исполняемый тип, а затем выполняется.

Оператор PostScript runаналогичен по функциональности, но вместо этого интерпретатор сам интерпретирует выражения PostScript в файле.

(file.ps) запустить 

Питон

В Python функция evalв своей простейшей форме оценивает одно выражение.

evalпример (интерактивная оболочка):

>>> x  =  1 >>> eval ( 'x + 1' ) 2 >>> eval ( 'x' ) 1

Функция evalпринимает два необязательных аргумента globalи locals, которые позволяют программисту настроить ограниченную среду для вычисления выражения.

Оператор exec(или execфункция в Python 3.x) выполняет операторы:

execпример (интерактивная оболочка):

>>> x  =  1 >>> y  =  1 >>> exec  "x += 1; y -= 1" >>> x 2 >>> y 0

Наиболее общей формой оценки операторов/выражений является использование объектов кода. Их можно создать, вызвав compile()функцию и указав ей, какой тип входных данных она должна скомпилировать: оператор " exec", evalоператор " " или singleоператор " ":

compileпример (интерактивная оболочка):

>>> x  =  1 >>> y  =  2 >>> eval  ( compile  ( «print 'x + y = ', x + y» ,  «compile-sample.py» ,  «single» )) x + y = 3

Д

D является статически компилируемым языком и поэтому не включает evalоператор " " в традиционном смысле, но включает связанный с ним mixinоператор " ". Разница в том, что если " eval" интерпретирует строку как код во время выполнения, то с " mixin" строка статически компилируется как обычный код и должна быть известна во время компиляции. Например:

импорт стандартный . стдио ; void main () { int num = 0 ; миксин ( "num++;" ); записьln ( число ); // Печатает 1. }         

Приведенный выше пример будет скомпилирован в точно такие же инструкции языка ассемблера, как если бы " num++;" был написан напрямую, а не в примешанном виде. Аргумент mixin не обязательно должен быть строковым литералом, это могут быть произвольные выражения, приводящие к строковому значению, включая функцию. вызовы, которые можно оценить во время компиляции.

Холодный синтез

Функция ColdFusion позволяетevaluate оценивать строковое выражение во время выполнения.

<cfset  x  =  "int(1+1)" > <cfset  y  =  Evaluate ( x ) >

Это особенно полезно, когда вам нужно программно выбрать переменную, из которой вы хотите прочитать.

<cfset  x  =  Evaluate ( "имя_запроса. #имя_столбца# [номер_строки]" ) >

Рубин

Интерпретатор языка программирования Ruby предлагает evalфункцию, аналогичную Python или Perl, а также позволяет указать область действия или привязку .

Помимо указания привязки функции, его evalтакже можно использовать для оценки выражения в конкретной привязке определения класса или привязке экземпляра объекта, что позволяет расширять классы с помощью новых методов, указанных в строках.

a = 1 eval ( 'a + 1' ) # (оценивается как 2)   # оценка в контексте def get_binding ( a ) привязка end eval ( 'a+1' , get_binding ( 3 )) # (оценивается как 4, потому что 'a' в контексте get_binding равна 3)   
класс Тест ; окончание теста . class_eval ( "def hello; return 'hello';end" ) # добавляем метод "hello" в этот класс Test . новый . hello # оценивается как «привет»    

Форт

Большинство стандартных реализаций Форта имеют два варианта eval: EVALUATEи INTERPRET.

Пример кода Win32FORTH:

 S" 2 2 + . " EVALUATE \ Выходы "4"   

БАЗОВЫЙ

РЕАЛбазовый

В REALbasic есть класс RBScript , который может выполнять код REALbasic во время выполнения. RBScript очень изолирован — в нем присутствуют только самые основные функции языка, и вы должны предоставить ему доступ к тому, что вы хотите. При желании вы можете назначить объект свойству контекста. Это позволяет коду RBScript вызывать функции и использовать свойства объекта контекста. Однако он по-прежнему ограничен пониманием только самых основных типов, поэтому, если у вас есть функция, возвращающая Dictionary или MySpiffyObject, RBScript не сможет ее использовать. Вы также можете взаимодействовать со своим RBScript через события печати и ввода.

VBScript

Microsoft VBScript, который является интерпретируемым языком, имеет две конструкции. Eval— это оценщик функций, который может включать вызовы пользовательских функций. (Эти функции могут иметь побочные эффекты, такие как изменение значений глобальных переменных.) Executeвыполняет один или несколько операторов, разделенных двоеточиями, которые могут изменить глобальное состояние.

И VBScript, и JScript evalдоступны разработчикам скомпилированных приложений Windows (написанных на языках, не поддерживающих Eval) через элемент управления ActiveX, называемый Microsoft Script Control, метод Eval которого может быть вызван кодом приложения. Чтобы поддерживать вызов пользовательских функций, необходимо сначала инициализировать элемент управления с помощью метода AddCode, который загружает строку (или строковый ресурс), содержащую библиотеку пользовательских функций, определенных на выбранном языке, перед вызовом Eval. .

Visual Basic для приложений

Visual Basic для приложений (VBA), язык программирования Microsoft Office, представляет собой язык виртуальных машин, на котором среда выполнения компилирует и запускает p-код . Его разновидность Eval поддерживает только вычисление выражений, при этом выражение может включать определяемые пользователем функции и объекты (но не имена определяемых пользователем переменных). Следует отметить, что оценщик отличается от VBS, и вызов определенных пользовательских функций может работать в VBA иначе, чем тот же код в VBScript.

Болтовня

Поскольку классы компилятора Smalltalk являются частью стандартной библиотеки классов и обычно присутствуют во время выполнения, их можно использовать для оценки строки кода.

Компилятор  оценивает: '1 + 2'

Поскольку определения классов и методов также реализуются посредством отправки сообщений (объектам класса), возможны даже изменения кода:

Компилятор  оценивает: 'Подкласс объекта:#Foo'

Ткл

В языке программирования Tcl есть команда под названием eval, которая выполняет исходный код, предоставленный в качестве аргумента. Tcl представляет весь исходный код в виде строк с фигурными скобками, действующими как кавычки, так что аргумент может evalиметь то же форматирование, что и любой другой исходный код.

set  foo { while {[ incr i ] < 10 } { puts "$i в квадрате равно [expr $i*$i]" } } eval $foo      

бс

bs имеет evalфункцию, которая принимает один строковый аргумент. Функция является одновременно оценщиком выражений и исполнителем операторов. В последней роли его также можно использовать для обработки ошибок. Следующие примеры и текст взяты со bs страницы руководства , приведенной в Руководстве программиста UNIX System V версии 3.2. [6]

Строковый аргумент оценивается как bsвыражение. Функция удобна для преобразования числовых строк во внутреннюю числовую форму. Также можно evalиспользовать в качестве грубой формы косвенности, как показано ниже (обратите внимание, что в bs( _подчеркивание) является оператором конкатенации.):

name = "xyz"
eval ( "++" _ имя )    

который увеличивает переменную xyz.

Кроме того, , evalкоторому предшествует оператор запроса ?, позволяет пользователю контролировать bsвозникновение ошибок. Например:

?eval ( "open(\"X\", \"XXX\", \"r\")" )

возвращает нулевое значение, если файл с именем «XXX» отсутствует (вместо остановки программы пользователя).

Следующее выполняет a gotoдля метки L(если она существует):

метка = «L» , если ! ( ?eval ( "goto" _label )) puterr = "без метки "        

Интерпретаторы командной строки

оболочки Unix

Команда eval присутствует во всех оболочках Unix , включая исходную «sh» ( оболочка Bourne ). Он объединяет все аргументы с пробелами, затем повторно анализирует и выполняет результат как команду. sh(1) –  Руководство по основным командам FreeBSD

Windows PowerShell

В Windows PowerShell командлет Invoke-Expressionслужит той же цели, что и функция eval в таких языках программирования, как JavaScript, PHP и Python. Командлет запускает любое выражение Windows PowerShell, предоставленное в виде параметра команды в виде строки, и выводит результат указанного выражения. Обычно выходные данные командлета имеют тот же тип, что и результат выполнения выражения. Однако, если результатом является пустой массив, выводится $null. Если результатом является массив из одного элемента, он выводит этот единственный элемент. Подобно JavaScript, Windows PowerShell позволяет оставлять последнюю точку с запятой.

Пример в качестве средства оценки выражений:

PS > $foo  =  2 PS > выражение вызова  '$foo + 2'

Пример в качестве исполнителя оператора:

PS > $foo  =  2 PS > ignore-expression  '$foo += 2; $фу'

Микрокод

В 1966 году IBM Conversational Programming System (CPS) представила микропрограммируемую функцию EVALдля выполнения «интерпретационной оценки выражений, записанных в модифицированной польской строковой нотации » на IBM System/360 Model 50 . [7] Микрокодирование этой функции было «существенно» более чем в пять раз быстрее по сравнению с программой, которая интерпретировала оператор присваивания . [8]

Теория

В теоретической информатике обычно проводят четкое различие между eval и apply . Под Eval понимается этап преобразования строки в кавычках в вызываемую функцию и ее аргументы, тогда как Apply — это фактический вызов функции с заданным набором аргументов. Это различие особенно заметно в функциональных языках и языках, основанных на лямбда-исчислении , таких как LISP и Scheme . Так, например, в Scheme различие заключается между

( оценка ' ( ж x ) )   

где должна быть вычислена форма (fx), и

( применить f ( список x ))   

где функция f должна вызываться с аргументом x .

Eval и apply — два взаимозависимых компонента цикла eval-apply , который составляет суть оценки Lisp, описанной в SICP . [9]

В теории категорий морфизм eval используется для определения замкнутой моноидальной категории . Так, например, категория множеств с функциями, взятыми в качестве морфизмов, и декартовым произведением , взятым в качестве произведения , образует декартову замкнутую категорию . Здесь eval (или, собственно говоря, apply ) вместе со своим правым сопряженным , currying , образуют просто типизированное лямбда-исчисление , которое можно интерпретировать как морфизмы декартовых замкнутых категорий.

Смотрите также

Рекомендации

  1. ^ "Flash 8 LiveDocs" . 10 октября 2006 г. Архивировано из оригинала 10 октября 2006 г.
  2. ^ Библиотека оценки ActionScript 3
  3. ^ "API D.eval" . Архивировано из оригинала 14 марта 2013 г.
  4. ^ Джон Маккарти, «История Лиспа - Реализация Лиспа»
  5. ^ «PHP: eval — Руководство» . PHP.net .Проверено 10 сентября 2015 г.
  6. ^ «Команды и утилиты тома 1» . Руководство программиста UNIX (PDF) . АТ&Т. 1986. с. 41.
  7. ^ Аллен-Бэбкок. «Проект микропрограммы EVAL» (PDF) . Bitsavers.org . Проверено 17 января 2016 г.
  8. ^ Рочестер, Натаниэль. «Отчет о ходе работы системы диалогового программирования» (PDF) . Bitsavers.org . Проверено 17 января 2016 г.
  9. ^ Метациркулярный оценщик (SICP, раздел 4.1)

Внешние ссылки