2009-06-25 16 views
5

Peter Norvig en PAIP dice:
"en ceceos modernas ... eval se usa con menos frecuencia (de hecho, en el Esquema no hay eval en absoluto)" "si usted se encuentra usando eval, se probablemente estén haciendo lo incorrecto ".EVAL en el Esquema

¿Cuáles son algunas de las formas de eludir el uso de eval en el esquema? ¿Hay algún caso en que eval sea absolutamente necesario?

Respuesta

7

Hay casos en los que eval es necesario, pero siempre implican programas avanzados que hacen cosas como cargar dinámicamente algún código (por ejemplo, un servlet en un servidor web). En cuanto a la forma de "eludir" su uso, eso depende del problema real que intentas resolver, no hay una solución mágica para evitar eval a excepción de ... eval.

(Por cierto, mi suposición es que PAIP fue escrito hace mucho tiempo, antes de eval se añadió al Informe Esquema.)

+0

Lo siento, no podría ser más específico sobre lo que quería en la pregunta. Pero lo que es interesante es que siempre pensé que eval siempre era una parte integral de Scheme. De todos modos, espero ver más usos y 'abusos' de eval en CS G111. :) – unj2

+1

Sí, 'eval' * es * una parte integral de Scheme, pero solo es realmente necesario en casos avanzados. La regla de oro es: si no conoce los motivos técnicos que requieren que use 'eval', entonces * no * lo necesita. (¡Y esta es una respuesta seria!) En cualquier caso, sí, tendrás mucha 'evaluación' en CSG111 si vas a tomarla, y con suerte si lo recuerdas, pregúntame al respecto. –

1

Primero, PAIP está escrito para Common Lisp, no Scheme, así que no sé si él diría lo mismo. Las macros CL hacen casi lo mismo que eval, aunque en tiempo de compilación en lugar de tiempo de ejecución, y hay otras cosas que podría hacer. Si me mostraras un ejemplo del uso de eval en Common Lisp, podría intentar encontrar otros métodos para hacer lo mismo.

No soy un programador de esquemas. Solo puedo hablar desde la perspectiva de Norvig, como programador de Common Lisp. No creo que estuviera hablando de Scheme, y no sé si conocía o conocía a Scheme particularmente bien.

En segundo lugar, Norvig dice "probablemente estás haciendo lo incorrecto" en lugar de "estás haciendo lo incorrecto". Esto implica que, por lo que él sabe, hay momentos en que eval es lo correcto para usar. En un lenguaje como C, diría lo mismo sobre goto, aunque son bastante útiles en algunas circunstancias restringidas, pero la mayoría del uso de goto es de personas que no conocen nada mejor.

+0

"No sé si él conoce a Scheme particularmente bien". Esta declaración es bastante increíble. "hay momentos en que eval es lo correcto para usar". Esa fue mi segunda pregunta. Como programadores en ejercicio, ¿has usado eval? – unj2

+1

Obviamente, Norvig es extremadamente bueno en Common Lisp, ya que escribió un libro verdaderamente excelente sobre él. Eso no se aplica a Scheme. ¿Sería Stroustrup necesariamente una buena autoridad sobre la mejor manera de hacer algo en Java o Objective-C? Esa familia de idiomas no es más dispares que la familia Lisp, incluidos Common Lisp y Scheme. –

+0

hmmm implementa esquema en lisp ... bueno, no lo sé. pero supongo que se encuentra en el espectro "sabe particularmente bien". – unj2

-1

Puede escribir un intérprete de esquema en el esquema. Tal es ciertamente posible, pero no es práctico.

De acuerdo, esta es una respuesta general, ya que no tengo un esquema usado, pero puede ser de ayuda. :)

+0

Aquí no está cerca de la respuesta que quería. :) – unj2

4

Está equivocado. Por supuesto, hay eval en Scheme.

+0

¿Qué esquema? No creo que r4rs requiera que eval esté presente en absoluto. – Aaron

+3

R5RS http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_sec_6.5 – newacct

+3

@newacct PAIP llegó en 1992 y el R4RS no tenía eval. R5Rs llegó en 1998 y agregó eval, dynamic-wind y values ​​:) – Sylwester

0

Uno de los usos que he visto para 'eval' en entornos de scripts es parametrizar algunos código con valores de tiempo de ejecución. por ejemplo, en psuedo-C:

param = read_integer(); 
fn = eval("int lambda(int x) { 
      int param = " + to_string(param) + "; 
      return param*x; }"); 

Espero que encuentres eso realmente feo. ¿Pegar cadenas para crear código en tiempo de ejecución? Ick. En Scheme y otros Lisps de ámbito léxico, puede realizar funciones parametrizadas sin usar eval.

(define make-my-fn 
    (lambda (param) 
    (lambda (x) (* param x))) 

(let* ([ param (read-integer) ] 
     [ fn  (make-my-fn param ]) 
    ;; etc. 
) 

Como se mencionó, la carga dinámica de código y tales todavía necesitan eval, pero el código parametrizada y la composición de código se pueden producir con funciones de primera clase.

3

Necesitará eval en algunos casos muy raros. El caso que viene primero a la mente es cuando construirás un programa con un programa y luego lo ejecutarás. Esto ocurre principalmente con algoritmo genético por ejemplo. En este caso, construyes muchos programas aleatorios que necesitarás ejecutar.Al tener eval en conjunto con el código que es datos, lisp es el lenguaje de programación más fácil de hacer algoritmo genético.

Tener estas propiedades tiene un gran costo (en términos de velocidad y tamaño de su programa) porque eliminará toda posibilidad de optimización del tiempo de compilación en el código que será evacuado y deberá mantener el intérprete completo en su binario resultante.

Como resultado, se considera un diseño deficiente para usar eval cuando se puede evitar.

3

La afirmación de que Scheme no tiene eval es inexacta al menos para las versiones más recientes del estándar Scheme (R5RS y posterior). Por lo general, lo que desea es una macro en su lugar, que generará el código en el momento de la compilación.

Es cierto que debe evitarse eval. Para empezar, nunca he visto una definición satisfactoria de cómo debería comportarse, por ejemplo:

  1. ¿Qué expresiones de entorno se deben evaluar cuando no se pasa el entorno?
  2. Cuando pasa en un entorno, ¿cómo funcionan? Por ejemplo, los estándares no especifican ninguna forma de vincular previamente un valor en ese objeto de entorno.

Dicho esto, he trabajado con una aplicación que utiliza el esquema eval para generar código de forma dinámica en tiempo de ejecución para los casos en los que la estructura de la computación no puede ser conocido en tiempo de compilación. La intención ha sido obtener el sistema Scheme en compilar el código en tiempo de ejecución por razones de rendimiento, y la dificultad es que no hay una forma estándar de decirle a un sistema Scheme que "compile este código".

No hace falta decir también que eval puede ser un gran riesgo de seguridad. Nunca debe eval nada que no tenga un gran muro de separación de la entrada del usuario. Básicamente, si desea usar eval de forma segura, debe hacerlo en el contexto de la fase de generación de código de un sistema similar al compilador, después de haber analizado alguna entrada (¡utilizando una gramática ampliamente definida!).