2010-10-05 7 views
10

El Common Lisp hyperspec dice en la entrada funcall que¿Cuándo utilizas "apply" y cuándo "funcall"?

(funcall function arg1 arg2 ...) 
== (apply function arg1 arg2 ... nil) 
== (apply function (list arg1 arg2 ...)) 

Puesto que son de alguna manera equivalente, cuándo se usa apply, y cuando funcall?

Respuesta

17

Debe utilizar funcall si usted tiene uno o más argumentos separados y apply si tiene sus argumentos en una lista

(defun passargs (&rest args) (apply #'myfun args)) 

o

(defun passargs (a b) (funcall #'myfun a b)) 
1

Bueno, yo creo que una buena regla general sería be: use apply cuando no puedes usar funcall: este último es más claro pero también es menos general que apply porque no te permite llamar a una función cuyo número de argumentos solo se conoce en tiempo de ejecución.

Por supuesto que no es más que una buena práctica y podría hacer sistemáticamente esto de la manera fea (utilizando sistemáticamente aplica), pero como te habrás dado cuenta, utilizando la forma feo cuando una manera muy similar pero más limpio está disponible se no muy común-lisp-y.

Ejemplo de la función que debe aplicarse en lugar de funcall: podrías aplicar un mapa de tal manera que (map #'+ '(1 2) '(2 3)) y (map #'+ '(1 2) '(2 3) '(3 4)) tanto el trabajo (que es el caso de la función estándar) sin necesidad de utilizar aplicar (o eval, que es trampa) ?

EDITAR: como también se ha señalado, sería tonto para escribir: (funcall func (first list) (second list) (third list) etc.) en lugar de (apply func list).

5

apply es útil cuando la lista de argumentos se conoce solo en el tiempo de ejecución, especialmente cuando los argumentos se leen dinámicamente como una lista. Todavía puede usar funcall aquí, pero tiene que descomprimir los argumentos individuales de la lista, lo cual es inconveniente. También puede usar apply como funcall pasando los argumentos individuales. Lo único que requiere es que el último argumento debe ser una lista:

> (funcall #'+ 1 2) 
3 
> (apply #'+ 1 2()) 
3 
Cuestiones relacionadas