Pregunta

Finalmente empecé a aprender los lenguajes funcionales (Emacs Lisp) y se hace una distinción explícita entre las funciones y formas especiales, tales como el control de flujo, por ejemplo si.

¿Hay una razón fundamental / teórica por la forma especial son distintas de las funciones? Realice cualquiera lenguajes proporcionan if funcional?

Gracias

¿Fue útil?

Solución

Con evaluación ansiosos se requiere la distinción, idiomas con la evaluación perezosa (es decir Haskell) si et al. pueden ser funciones.

Evaluación Eager:. Se evalúan los argumentos de la función antes llamar a la función, y sólo los resultados se pasa a la función

La evaluación perezosa:. Los argumentos de una función evaluada si y sólo si se accede a ellos

Otros consejos

Si if era una función normal, entonces ambos sus argumentos -la a continuación, forman y forma de persona , no tuvimos suerte ambos evaluarse antes llamar a la función if, porque esa es la Estado de href="http://www.lispworks.com/documentation/HyperSpec/Body/03_ababc.htm" evaluación de la función : evaluar todos los argumentos para producir valores, a continuación, disponer que secuencia de valores como argumentos de la función designada por el primer símbolo en la lista.

En lugar de ello, la if lo que quiere hacer es evaluar exactamente uno de los a continuación, forma y forma de persona , pero no ambos. Con el fin de suprimir la evaluación de uno u otro, necesita ya sea una macro o un forma especial .

En idiomas como Emacs Lisp y Common Lisp, formas especiales están incorporados en las construcciones del lenguaje. Ellos tienen diferentes reglas de evaluación que las llamadas a funciones normales. Para las llamadas a funciones normales se evalúan todos los argumentos. Por lo tanto, no se puede escribir un SI como una función normal - la condición determina la cláusula obtiene evaluado. También por lo general no se puede escribir sus propias formas especiales -. En Common Lisp no hay ninguna construcción del lenguaje para la definición de una forma especial (aunque las implementaciones individuales deben haber implementado las ya existentes de alguna manera esto conduce a las macros con macros se puede escribir una transformación sintáctica. que transforma una expresión en otro. para ser capaz de escribir SI como una macro, es necesario tener otra forma condicional, que se puede utilizar para el código transformado. Lisp proporciona condicionales como construcciones básicas. Asumamos COND es una construcción tan básico , entonces se podría expandirse si en un uso del cond.

MI-IF como una macro en Common Lisp:

(defmacro my-if (condition true-clause false-clause)
   `(cond (,condition ,true-clause)
          (t ,false-clause)))

Entonces

(my-if (foo-p) 'one 'two)

obtiene expandido a

(cond ((foo-p) 'one)
      (t 'two))

Para completar: No hay formas especiales en el idioma Pico por ejemplo, y es if una función primitiva , mientras que Pico está inspirado en el Esquema de evaluación y tiene ganas de manera predeterminada.

En el esquema se podría escribir

(define (true t f)
  (t))

(define (false t f)
  (f))

(define (function_if c t e)
  (c t e))

y

(function_if true (lambda () 'true) (lambda () 'false))
==> true

Lo que hace este manejable en Pico es que se puede definir parámetros funcionales que toman argumentos funcionales que son "automáticamente" retrasaron. Esto significa que usted no tiene que hacer la envoltura interior lambdas mismo. Por lo tanto, la evaluación de Pico tiene ganas pero con la evaluación perezosa de la demanda, evitando la necesidad de formas especiales.

Por lo tanto, en la sintaxis de esquema con los parámetros funcionales se puede codificar booleanos como:

(define (true (t) (f))
  (t))

(define (false (t) (f))
  (f))

A continuación funcionar si se convierte en:

(define (function_if c (t) (e))
  (c (t) (e)))

y

(function_if true 'true 'false)
==> true

Como otro ejemplo, la definición de la and función es (define (and p (q)) (p (q) false)).

Del mismo modo se puede definir or, not, while, for, ... como funciones, utilizando la codificación por encima de booleanos.

Respuesta corta:. No

Long (a) no hay respuesta: (si ...) requiere que usted controla el orden de evaluación de los argumentos. Lisp, siendo una lengua ansiosa no puede hacer esto en una función.

Solución: hacerlo en una macro:

(defmacro _if (cnd true false)
    (let (  (gcond (gensym))
            (gresp (gensym)))
        `(let ( (,gcond ,cnd) ;`#quotes
                (,gresp nil))        
            (and ,gcond       (setf ,gresp (multiple-value-list ,true)))
            (and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
            (values-list ,gresp))))

Por ejemplo:

[dsm@localhost:~]$ clisp -q
[1]> (defmacro _if (cnd true false)
    (let (  (gcond (gensym))
            (gresp (gensym)))
        `(let ( (,gcond ,cnd) ;`#quotes
                (,gresp nil))        
            (and ,gcond       (setf ,gresp (multiple-value-list ,true)))
            (and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
            (values-list ,gresp))))
_IF
[2]> (_if (= 1 1) (+ 2 3) "bar")
5
[3]> (_if (= 1 2) (+ 2 3) "bar")
"bar"
[4]> 

En Scala es posible modelar con if correcta evaluación de efectos secundarios usando argumentos de llamada por nombre.

def If[A](cond : Boolean, truePart : => A, falsePart : => A) = if (cond) truePart else falsePart

Estos característica se puede utilizar para modelar un montón de nuevas estructuras de control también.

Si pudiera ser una función en un lenguaje funcional que tiene de llamada por nombre semántica (evaluación perezosa), como en el cálculo lambda o Algol. De hecho eso es, creo, en el centro de la relación entre las máquinas de Turing y Lambda cálculo como bases equivalentes para la computación. Sin embargo, en los idiomas que tienen efectos secundarios (como las asignaciones a variables) que no es muy útil, porque cuando las cosas suceden es importante.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top