stringtranslate.com

оценка

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

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

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

session [ 'authenticated' ]  =  Ложные данные  =  get_data () foo  =  eval ( data )

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

Выполнение

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

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

ECMAScript

JavaScript

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

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

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

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

foo = 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] и API D.eval [3] были проектами разработки по созданию эквивалентов evalв ActionScript 3. Оба проекта были завершены, поскольку Adobe Flash Player подошел к концу .

Лисп

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

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

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

Вот пример кода Lisp:

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

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

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

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

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

Перл

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

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

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

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

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

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

PHP

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

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

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

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

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

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

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

Луа

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

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

loadstring ( "print('Привет, мир!')" )()

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

a  =  1 f  =  loadstring ( "return a + 1" )  -- компилирует выражение в анонимную функцию print ( f ())  -- выполняет (и выводит результат '2')

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

load ( "print('Привет ' .. a)" ,  "" ,  "t" ,  {  a  =  "Мир!" ,  print  =  print  })()

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

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

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

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

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

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

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

(файл.ps) запустить 

Питон

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

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

>>> x  =  1 >>> оценка ( 'x + 1' ) 2 >>> оценка ( '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" строка статически компилируется как обычный код и должна быть известна во время компиляции. Например:

импортировать std.stdio ; void main () { int num = 0 ; mixin ( "num++;" ); writeln ( num ); // Выводит 1. }         

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

Холодный фьюжн

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

<cfset  x  =  "int(1+1)" > <cfset  y  =  Вычислить ( x ) >

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

<cfset  x  =  Вычислить ( "queryname. #columnname# [rownumber]" ) >

Рубин

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

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

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

Вперед

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

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

 S" 2 2 + . " ОЦЕНИТЬ \ Выводит "4"   

БАЗОВЫЙ

РЕАЛЬНЫЙбазовый

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

VBScript

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

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

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

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

Smalltalk

Поскольку классы компилятора 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 Release 3.2. [6]

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

имя = "xyz"
оценка ( "++" _ имя )    

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

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

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

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

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

label = "L" if ! ( ?eval ( "goto " _ label )) puterr = "нет метки"        

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

Оболочки Unix

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

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 > invoke-expression  '$foo += 2; $foo'

Микрокод

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

Теория

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

( оценить ' ( f x ) )   

где необходимо оценить форму (fx), и

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

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

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

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

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

Ссылки

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

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