2012-03-15 29 views
14

¿Por qué tenemos que usar funcall para llamar a funciones de orden superior en Common Lisp? Por ejemplo, ¿por qué tenemos que utilizar:¿Por qué necesitamos funcall en Lisp?

(defun foo (test-func args) 
    (funcall test-func args)) 

en lugar de la más simple:

(defun bar (test-func args) 
    (test-func args)) 

Viniendo de un fondo de procedimiento, estoy un poco sorprendido por que desde las lenguas que estoy más solía (por ejemplo, Python, C#) no necesita la distinción. En particular, al menos en el nivel de la fuente, el compilador de C# lo transforma en algo como func.invoke().

El único problema que veo es que esto significaría que ya no podríamos llamar a una función global test-func porque estaría sombreada, pero eso no es un problema.

+3

"No hay problema" es el quid de la cuestión. En la práctica, creo que no es un problema llamar a funcall y sería un inconveniente si tuviera que elegir nombres creativos/extraños para las variables para evitar choques con CAR, LIST, REST, etc. – Xach

Respuesta

16

en sentido estricto, no se necesitarían funcall, pero hay algunas ceceos (list-2 implementaciones, tales como Common Lisp) que separan el espacio nombre de la variable del espacio de nombres función. Las implementaciones de List-1 (por ejemplo, Scheme) no hacen esta distinción.

Más específicamente, en su caso, test-func se encuentra en el espacio de nombre de la variable.

(defun foo (test-func args) 
    (funcall test-func args)) 

Por lo tanto, necesita una construcción que realmente busque el objeto de función asociado con esta variable en el espacio de nombre de la variable. En Common Lisp, esta construcción es funcall.

Véase también this answer.

12

La mayoría de Lisps tienen dos espacios de nombres (funciones y variables). Se busca un nombre en el espacio de nombres de la función cuando aparece como el primer elemento en una expresión S, y en el espacio de nombres de la variable en caso contrario. Esto le permite nombrar sus variables sin preocuparse de si sombrean funciones: así puede nombrar su variable list en lugar de tener que dividirla en lst.

Sin embargo, esto significa que cuando vaya a guardar una función de una variable, no se puede llamar normal:

(setq list #'+) ; updates list in the variable namespace 
(list 1 2 3) => (1 2 3) ; looks up list in the function namespace 

De ahí la necesidad de funcall y apply:

(funcall list 1 2 3) => 6 ; looks up list in the variable namespace 

(No todos los Lisps tienen dos espacios de nombres: Scheme es un ejemplo de un Lisp con solo un espacio de nombres).

+0

Sí, la ventaja de no sombrear funciones es agradable, pero por otro lado tenemos los casos especiales para las funciones ... bueno, asumo que ya que no tenemos que preocuparnos por el posicionamiento del paréntesis en el ceceo, necesitamos otras guerras religiosas;) Como usted y Diego respondieron mi pregunta muy bien, fui con el tiempo como un desempate y aceptó la respuesta de Diego. – Voo

-2

En Common Lisp, cada símbolo se puede asociar con su symbol-function y su symbol-value, entre otras cosas.Al leer una lista, por defecto, Common Lisp interpreta:

  • arg1 como una función y así recupera test-func 's symbol-function, que no está definido - por lo tanto la función bar no funciona
  • arg2 como algo que debe eval ed - por lo tanto la función foo recupera test-func 's symbol-value, que, en su caso, pasa a ser una función
+0

esto no es lo que hace una implementación Common Lisp. Es posible que desee leer sobre enlaces léxicos. –

1

Tenga en cuenta que en cualquier Lisp, si desea llamar a una función de alguna manera que no sea

(function fixed arg u ments) 

tiene que usar algo en la primera posición de la forma que no sea la función de todos modos. En algunos dialectos, si F es una variable que tiene una función, sólo puede hacer esto:

(f a b c) ;; no funcall 

Pero en casi todos los dialectos, no se puede quitar el apply

(apply f args-list) ;; Common Lisp or Scheme: same 

Si Está corriendo en funcall siendo una molestia, simplemente no está usando suficientes aplicadores interesantes sobre sus argumentos funcionales. :)

Cuestiones relacionadas