Why do we need funcall in Lisp?

巧了我就是萌 提交于 2019-11-27 13:39:31
Diego Sevilla

Strictly speaking, funcall would not be needed, but there are some lisps (list-2 implementations, such as Common Lisp) that separate the variable name space of the function name space. List-1 implementations (e.g. Scheme) do not make this distinction.

More specifically, in your case, test-func is in the variable name space.

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

Therefore you need a construct that actually searches the function object associated with this variable in the variable name space. In Common Lisp this construct is funcall.

See also this answer.

The majority of Lisps have two namespaces (functions and variables). A name is looked up in the function namespace when it appears as the first element in an S-expression, and in the variable namespace otherwise. This allows you to name your variables without worrying about whether they shadow functions: so you can name your variable list instead of having to mangle it into lst.

However, this means that when you store a function in a variable, you can't call it normally:

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

Hence the need for funcall and apply:

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

(Not all Lisps have two namespaces: Scheme is an example of a Lisp with just one namespace.)

In Common Lisp, each symbol can be associated with its symbol-function and its symbol-value, among other things. When reading a list, by default, Common Lisp interprets:

  • arg1 as a function and so retrieves test-func's symbol-function, which is undefined -- thus function bar doesn't work
  • arg2 as something to be evaled -- thus function foo retrieves test-func's symbol-value, which, in your case, happens to be a function
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!