En algunos lenguajes de programación , eval
, abreviatura del inglés evaluating, es una función que evalúa una cadena como si fuera una expresión en el lenguaje y devuelve un resultado ; en otros, ejecuta múltiples líneas de código como si se hubieran incluido en lugar de la línea que incluye el eval
. La entrada a eval
no es necesariamente una cadena; puede ser una representación estructurada de código, como un árbol de sintaxis abstracta (como las formas de Lisp ), o de tipo especial como code
(como en Python). El análogo para una declaración es exec , que ejecuta una cadena (o código en otro formato) como si fuera una declaración; en algunos lenguajes, como Python, ambos están presentes, mientras que en otros lenguajes solo está uno de ellos eval
o exec
.
El uso eval
de datos de una fuente no confiable puede generar vulnerabilidades de seguridad. Por ejemplo, suponiendo que la get_data()
función obtiene datos de Internet, este código Python es inseguro:
sesión [ 'autenticado' ] = Falso datos = obtener_datos () foo = eval ( datos )
Un atacante podría proporcionar al programa la cadena "session.update(authenticated=True)"
como datos, lo que actualizaría el session
diccionario para establecer una clave autenticada como Verdadera. Para solucionar esto, todos los datos que se utilizarán con eval
deben ser escapados, o debe ejecutarse sin acceso a funciones potencialmente dañinas.
En los lenguajes interpretados , eval
casi siempre se implementa con el mismo intérprete que el código normal. En los lenguajes compilados , el mismo compilador utilizado para compilar programas puede estar integrado en los programas que utilizan la eval
función; a veces se utilizan intérpretes independientes, aunque esto da como resultado la duplicación del código .
En JavaScript , eval
es una especie de híbrido entre un evaluador de expresiones y un ejecutor de sentencias. Devuelve el resultado de la última expresión evaluada.
Ejemplo como evaluador de expresiones:
foo = 2 ; alerta ( eval ( 'foo + 2' ));
Ejemplo como ejecutor de sentencia:
foo = 2 ; eval ( 'foo = foo + 2; alerta (foo);' );
Uno de los usos de JavaScript eval
es analizar texto JSON , tal vez como parte de un marco AjaxJSON.parse
. Sin embargo, los navegadores modernos ofrecen una alternativa más segura para esta tarea.
En ActionScript (el lenguaje de programación de Flash), eval
no se puede utilizar para evaluar expresiones arbitrarias. Según la documentación de Flash 8, su uso está limitado a expresiones que representan "el nombre de una variable, propiedad, objeto o clip de película que se desea recuperar. Este parámetro puede ser una cadena o una referencia directa a la instancia del objeto". [1]
ActionScript 3 no admite eval.
La biblioteca de evaluación ActionScript 3 [2] y la API D.eval [3] eran proyectos de desarrollo para crear equivalentes eval
en ActionScript 3. Ambos finalizaron, ya que Adobe Flash Player llegó al final de su vida útil .
Lisp fue el lenguaje original que utilizó una eval
función en 1958. De hecho, la definición de la eval
función condujo a la primera implementación del intérprete de lenguaje. [4]
Antes de que eval
se definiera la función, las funciones de Lisp se compilaban manualmente en instrucciones de lenguaje ensamblador . Sin embargo, una vez que la eval
función se había compilado manualmente, se utilizaba como parte de un simple bucle de lectura-evaluación-impresión que formó la base del primer intérprete de Lisp.
Las versiones posteriores de la función Lisp eval
también se han implementado como compiladores.
La eval
función en Lisp espera que se evalúe un formulario como su argumento. El valor resultante del formulario dado será el valor devuelto de la llamada a eval
.
Este es un ejemplo de código Lisp:
; Un formulario que llama a la función + con 1,2 y 3 como argumentos. ; Devuelve 6. ( + 1 2 3 ) ; En Lisp, cualquier formulario debe evaluarse, por lo tanto , ; se realizó la llamada a +. ; Podemos evitar que Lisp realice la evaluación de un formulario anteponiéndole el prefijo "'", por ejemplo: ( setq form1 ' ( + 1 2 3 )) ; Ahora form1 contiene un formulario que puede ser utilizado por eval, por ; ejemplo: ( eval form1 ) ; eval evaluó (+ 1 2 3) y devolvió 6.
Se sabe que Lisp es muy flexible, al igual que la eval
función. Por ejemplo, para evaluar el contenido de una cadena, primero habría que convertir la cadena a un formato Lisp mediante la read-from-string
función y luego habría que pasar el formato resultante a eval
:
( eval ( lectura-de-cadena "(formato t \"¡Hola mundo!!!~%\")" ))
Un punto de confusión importante es la cuestión de en qué contexto se evaluarán los símbolos del formulario. En el ejemplo anterior, form1
contiene el símbolo +
. La evaluación de este símbolo debe generar la función para la suma para que el ejemplo funcione como se pretende. Por lo tanto, algunos dialectos de Lisp permiten un parámetro adicional para eval
especificar el contexto de evaluación (similar a los argumentos opcionales para la función de Python eval
; consulte a continuación). Un ejemplo en el dialecto Scheme de Lisp (R 5 RS y posteriores):
;; Defina una forma simple como en el ejemplo anterior. ( define form2 ' ( + 5 2 )) ;Valor: form2 ;; Evalúa el formulario dentro del contexto inicial. ;; Un contexto para la evaluación se denomina "entorno" en la jerga de Scheme. ( eval form2 user-initial-environment ) ;Valor: 7 ;; Confundir el entorno inicial, de modo que + sea ;; un nombre para la función de resta. ( entorno-definir entorno-inicial-usuario '+ - ) ;Valor: + ;; Evalúe el formulario nuevamente. ;; Observe que el valor devuelto ha cambiado. ( eval form2 user-initial-environment ) ;Valor: 3
En Perl , la eval
función es una especie de híbrido entre un evaluador de expresiones y un ejecutor de sentencias. Devuelve el resultado de la última expresión evaluada (todas las sentencias son expresiones en la programación de Perl) y permite omitir el punto y coma final.
Ejemplo como evaluador de expresiones:
$foo = 2 ; imprimir eval ( '$foo + 2' ), "\n" ;
Ejemplo como ejecutor de sentencia:
$foo = 2 ; eval ( '$foo += 2; imprimir "$foo\n";' );
Perl también tiene eval
bloques , que sirven como mecanismo de manejo de excepciones (consulte Sintaxis de manejo de excepciones#Perl ). Esto difiere del uso anterior de eval
with strings en que el código dentro eval
de bloques se interpreta en tiempo de compilación en lugar de tiempo de ejecución, por lo que no es el significado de eval
utilizado en este artículo.
En PHP , eval
ejecuta el código en una cadena casi exactamente como si se hubiera colocado en el archivo en lugar de la llamada a eval()
. La única excepción es que los errores se informan como provenientes de una llamada a eval()
, y las instrucciones de retorno se convierten en el resultado de la función.
A diferencia de algunos lenguajes, el argumento eval
debe ser una cadena de una o más declaraciones completas, no solo expresiones; sin embargo, uno puede obtener la forma de "expresión" de eval
poniendo la expresión en una declaración de retorno, lo que hace eval
que se devuelva el resultado de esa expresión.
A diferencia de algunos lenguajes, PHP eval
es una "construcción del lenguaje" en lugar de una función, [5] y por lo tanto no se puede utilizar en algunos contextos en los que sí se pueden utilizar funciones, como las funciones de orden superior.
Ejemplo usando echo:
<?php $foo = "Hola, mundo! \n " ; eval ( 'echo "$foo";' ); ?>
Ejemplo que devuelve un valor:
<?php $foo = "Adiós, mundo! \n " ; //no funciona en PHP5 echo eval ( 'return $foo;' ); ?>
En Lua 5.1, loadstring
compila el código Lua en una función anónima.
Ejemplo como evaluador de expresiones:
loadstring ( "print('¡Hola mundo!')" )()
Ejemplo para realizar la evaluación en dos pasos:
a = 1 f = loadstring ( "return a + 1" ) - compila la expresión en una función anónima print ( f ()) - ejecuta (e imprime el resultado '2')
Lua 5.2 se desactualiza loadstring
en favor de la load
función existente, que se ha ampliado para aceptar cadenas. Además, permite proporcionar el entorno de la función directamente, ya que los entornos ahora son upvalues .
cargar ( "print('Hola ' .. a)" , "" , "t" , { a = "¡Mundo!" , print = print })()
El operador de PostScriptexec
toma un operando: si es un literal simple, lo vuelve a colocar en la pila. Sin embargo, si se toma una cadena que contiene una expresión PostScript, se puede convertir la cadena en un ejecutable que luego puede ser ejecutado por el intérprete, por ejemplo:
((Hola mundo) =) cvx exec
convierte la expresión PostScript
(Hola mundo) =
que extrae la cadena "Hola mundo" de la pila y la muestra en la pantalla, para que tenga un tipo ejecutable, luego se ejecuta.
El operador de PostScript run
es similar en funcionalidad pero, en cambio, el intérprete interpreta las expresiones PostScript en un archivo.
(archivo.ps) ejecutar
En Python , la eval
función en su forma más simple evalúa una sola expresión.
eval
Ejemplo (shell interactivo):
>>> x = 1 >>> eval ( 'x + 1' ) 2 >>> eval ( 'x' ) 1
La eval
función toma dos argumentos opcionales, global
y locals
, que permiten al programador configurar un entorno restringido para la evaluación de la expresión.
La exec
declaración (o la exec
función en Python 3.x) ejecuta declaraciones:
exec
Ejemplo (shell interactivo):
>>> x = 1 >>> y = 1 >>> exec "x += 1; y -= 1" >>> x 2 >>> y 0
La forma más general de evaluar declaraciones/expresiones es mediante objetos de código. Estos se pueden crear invocando la compile()
función y diciéndole qué tipo de entrada tiene que compilar: una exec
declaración " ", una eval
declaración " " o una single
declaración " ":
compile
Ejemplo (shell interactivo):
>>> x = 1 >>> y = 2 >>> eval ( compilar ( "imprimir 'x + y = ', x + y" , "compilar-muestra.py" , "single" )) x + y = 3
D es un lenguaje compilado estáticamente y, por lo tanto, no incluye una eval
declaración " " en el sentido tradicional, pero sí incluye la mixin
declaración relacionada " ". La diferencia es que, donde " eval
" interpreta una cadena como código en tiempo de ejecución, con un " mixin
" la cadena se compila estáticamente como código ordinario y debe conocerse en tiempo de compilación. Por ejemplo:
importar std . stdio ; void main () { int num = 0 ; mixin ( "num++;" ); writeln ( num ); // Imprime 1. }
El ejemplo anterior se compilará exactamente con las mismas instrucciones en lenguaje ensamblador como si " num++;
" se hubiera escrito directamente en lugar de mezclarlo. El argumento de mixin no necesita ser un literal de cadena, sino expresiones arbitrarias que resulten en un valor de cadena, incluidas las llamadas de función, que se pueden evaluar en tiempo de compilación.
La función de ColdFusionevaluate
le permite evaluar una expresión de cadena en tiempo de ejecución.
<cfset x = "int(1+1)" > <cfset y = Evaluar ( x ) >
Es especialmente útil cuando necesitas elegir programáticamente la variable que quieres leer.
<cfset x = Evaluate ( "nombreconsulta. #nombrecolumna# [númerofila]" ) >
El intérprete del lenguaje de programación Ruby ofrece una eval
función similar a Python o Perl, y también permite especificar un alcance o enlace .
Además de especificar el enlace de una función, eval
también se puede utilizar para evaluar una expresión dentro de un enlace de definición de clase específico o un enlace de instancia de objeto, lo que permite ampliar las clases con nuevos métodos especificados en cadenas.
a = 1 eval ( 'a + 1' ) # (evalúa a 2) # evaluar dentro de un contexto def get_binding ( a ) binding end eval ( 'a+1' , get_binding ( 3 )) # (se evalúa como 4, porque 'a' en el contexto de get_binding es 3)
clase Test ; fin Test . class_eval ( "def hola; return 'hola'; fin" ) # agrega un método 'hola' a esta clase Test . new . hola # evalúa a "hola"
La mayoría de las implementaciones estándar de Forth tienen dos variantes de eval
: EVALUATE
y INTERPRET
.
Ejemplo de código Win32FORTH:
S" 2 2 + . " EVALUAR \ Salida "4"
En REALbasic , hay una clase llamada RBScript que puede ejecutar código REALbasic en tiempo de ejecución. RBScript está muy restringido: solo están las características más básicas del lenguaje y debes permitirle el acceso a las cosas que quieres que tenga. Opcionalmente, puedes asignar un objeto a la propiedad de contexto. Esto permite que el código en RBScript llame a funciones y use propiedades del objeto de contexto. Sin embargo, todavía está limitado a comprender solo los tipos más básicos, por lo que si tienes una función que devuelve un Dictionary o MySpiffyObject, RBScript no podrá usarlo. También puedes comunicarte con tu RBScript a través de los eventos Print y Input.
VBScript de Microsoft, que es un lenguaje interpretado, tiene dos construcciones. Eval
es un evaluador de funciones que puede incluir llamadas a funciones definidas por el usuario. (Estas funciones pueden tener efectos secundarios, como cambiar los valores de las variables globales). Execute
ejecuta una o más instrucciones separadas por dos puntos, que pueden cambiar el estado global.
Tanto VBScript como JScript eval
están disponibles para los desarrolladores de aplicaciones compiladas de Windows (escritas en lenguajes que no admiten Eval) a través de un control ActiveX llamado Microsoft Script Control, cuyo método Eval puede ser invocado por el código de la aplicación. Para admitir la invocación de funciones definidas por el usuario, primero se debe inicializar el control con el método AddCode, que carga una cadena (o un recurso de cadena) que contiene una biblioteca de funciones definidas por el usuario en el lenguaje de la elección, antes de invocar Eval.
Visual Basic para Aplicaciones (VBA), el lenguaje de programación de Microsoft Office, es un lenguaje de máquina virtual en el que el entorno de ejecución compila y ejecuta código p . Su variante de Eval solo admite la evaluación de expresiones, donde la expresión puede incluir funciones y objetos definidos por el usuario (pero no nombres de variables definidos por el usuario). Cabe destacar que el evaluador es diferente de VBS y la invocación de ciertas funciones definidas por el usuario puede funcionar de manera diferente en VBA que el código idéntico en VBScript.
Como las clases del compilador de Smalltalk son parte de la biblioteca de clases estándar y generalmente están presentes en tiempo de ejecución, se pueden usar para evaluar una cadena de código.
El compilador evalúa: '1 + 2'
Dado que las definiciones de clases y métodos también se implementan mediante envíos de mensajes (a objetos de clase), incluso son posibles cambios en el código:
El compilador evalúa: 'Subclase de objeto: #Foo'
El lenguaje de programación Tcl tiene un comando llamado eval
, que ejecuta el código fuente proporcionado como argumento. Tcl representa todo el código fuente como cadenas, con llaves que actúan como comillas, de modo que el argumento to eval
puede tener el mismo formato que cualquier otro código fuente.
establecer foo { mientras {[ incr i ] < 10 } { pone "$i al cuadrado es [expr $i*$i]" } } eval $foo
bs tiene una eval
función que toma como argumento una cadena. La función es a la vez un evaluador de expresiones y un ejecutor de sentencias. En este último rol, también se puede utilizar para el manejo de errores. Los siguientes ejemplos y textos son de la bs
página del manual que aparece en el Manual del programador de UNIX System V Release 3.2. [6]
El argumento de cadena se evalúa como una
bs
expresión. La función es útil para convertir cadenas numéricas a formato numérico interno.eval
También se puede utilizar como una forma básica de indirección, como en el siguiente ejemplo (tenga en cuenta que, enbs
,_
(guión bajo) es el operador de concatenación):nombre = "xyz" eval ( "++" _ nombre )que incrementa la variable
xyz
.Además,
eval
precedido por el operador de interrogación,?
, permite al usuario controlarbs
las condiciones de error. Por ejemplo:?eval ( "abrir(\"X\", \"XXX\", \"r\")" )devuelve el valor cero si no hay ningún archivo llamado "XXX" (en lugar de detener el programa del usuario).
Lo siguiente ejecuta
goto
a la etiquetaL
(si existe):etiqueta = "L" si ! ( ?eval ( "goto " _ etiqueta )) puterr = "sin etiqueta"
El comando eval está presente en todos los shells de Unix , incluido el "sh" original ( Bourne shell ). Concatena todos los argumentos con espacios, luego vuelve a analizarlos y ejecuta el resultado como un comando. – Manual de comandos generales de FreeBSD
En Windows PowerShell , el Invoke-Expression
cmdlet cumple la misma función que la función eval en lenguajes de programación como JavaScript, PHP y Python. El cmdlet ejecuta cualquier expresión de Windows PowerShell que se proporcione como parámetro de comando en forma de cadena y genera el resultado de la expresión especificada. Por lo general, la salida del cmdlet es del mismo tipo que el resultado de ejecutar la expresión. Sin embargo, si el resultado es una matriz vacía, genera $null
. En caso de que el resultado sea una matriz de un solo elemento, genera ese único elemento. De manera similar a JavaScript, Windows PowerShell permite omitir el punto y coma final.
Ejemplo como evaluador de expresiones:
PS > $foo = 2 PS > expresión-invocación '$foo + 2'
Ejemplo como ejecutor de sentencia:
PS > $foo = 2 PS > expresión-invocación '$foo += 2; $foo'
En 1966, IBM Conversational Programming System (CPS) introdujo una función microprogramadaEVAL
para realizar una "evaluación interpretativa de expresiones escritas en una notación de cadena polaca modificada " en un IBM System/360 Modelo 50. [ 7] La microcodificación de esta función era "sustancialmente" más de cinco veces más rápida en comparación con un programa que interpretaba una declaración de asignación . [8]
En la informática teórica , se suele hacer una distinción cuidadosa entre eval y apply . Se entiende por eval el paso de convertir una cadena entre comillas en una función invocable y sus argumentos, mientras que apply es la llamada real de la función con un conjunto dado de argumentos. La distinción es particularmente notable en lenguajes funcionales y lenguajes basados en cálculo lambda , como LISP y Scheme . Así, por ejemplo, en Scheme, la distinción es entre
( eval ' ( fx ) )
donde se debe evaluar la forma (fx), y
( aplica f ( lista x ))
donde se debe llamar a la función f con el argumento x .
Eval y apply son los dos componentes interdependientes del ciclo eval-apply , que es la esencia de la evaluación de Lisp, descrita en SICP . [9]
En teoría de categorías , el morfismo eval se utiliza para definir la categoría monoidal cerrada . Así, por ejemplo, la categoría de conjuntos , con funciones tomadas como morfismos y el producto cartesiano tomado como producto , forma una categoría cartesiana cerrada . Aquí, eval (o, propiamente hablando, apply ) junto con su adjunto derecho , currying , forman el cálculo lambda de tipos simples , que puede interpretarse como los morfismos de categorías cartesianas cerradas.