为什么funcall没有语法糖?我们需要它很多。写(&#do-something arg0 arg1 arg2)
而不是(funcall do-something arg0 arg1 arg2)
之类的东西真是太棒了。为什么不添加像Ruby&#;;方法符号这样的东西?该语言中是否有某些内容?
答案 0 :(得分:7)
在语言中没有任何内容;您可以轻松地将该功能分配给其他名称,并使用它。例如,如果您想使用&
,您可以:
CL-USER> (setf (symbol-function '&) (symbol-function 'funcall))
#<FUNCTION FUNCALL>
CL-USER> (&'list 1 2 3)
(1 2 3)
CL-USER> (&'cons 'x 'y)
(X . Y)
(Stack Overflow最近有一个关于第一行不同方法的问题:How to stop evaluating lisp form when passed as function parameter?。)
赢得
(&#do-something arg0 arg1 arg2)
而非(funcall do-something arg0 arg1 arg2)
之类的内容真是太棒了吗?
可能不是。 Common Lisp是一种更喜欢函数和宏的表达名称的语言。名称funcall被识别,它清楚地表明发生了间接函数调用。我们为什么要模糊这一点?显然,大多数人发现funcall之间有足够的平衡可以写出&#34;和&#34;足够长的时间来描述&#34;。
为什么funcall没有语法糖?
您可以调用宏&#34;语法糖&#34;在Common Lisp中,但这里没有必要。 Funcall是一个函数,而不是一个特殊的形式或宏,所以它真的非常很容易用另一个名称别名,如上所示。大多数人不这样做的事实应该说一下它有多可取。
答案 1 :(得分:6)
funcall
没有语法,因为我们不需要它(或者,定义&#34; we&#34;)。我的意思是,在Lisp-2中,比如Common Lisp,这是一种权衡取舍,除非你做了一些沉重的lambda演算,否则你会习惯它。
如果您真的想使用更多succint语法,可以定义dispatch macro character:
(set-dispatch-macro-character
#\# #\&
#'(lambda (stream subchar arg)
(let ((args-var (gensym)))
`(lambda (&rest ,args-var)
(declare (dynamic-extent ,args-var))
(apply ,(read stream t nil t) ,args-var)))))
(let ((my-function #'max))
(#&my-function 1 3 2))
检查您的编译器是否会优化传递给lambda forms的dynamic-extent
和apply
&rest
个参数。
我建议不要将单个字符&
定义为macro character,因为它constituent character主要用于符号&optional
, &rest
, &key
, &allow-other-keys
, &aux
, &whole
, &body
and &environment
。
答案 2 :(得分:4)
如果你倾向于黑魔法:
(defun black-magic (stream sub-char numarg)
(declare (ignore sub-char numarg))
`(funcall ,@(read stream)))
(set-dispatch-macro-character
#\# #\! #'black-magic)
粗略的例子:
CL-USER> (defun foo (fn x y z)
#!(fn x y z))
FOO
CL-USER> (foo #'* 1 2 3)
6
CL-USER> (foo #'+ 1 1 1)
3
(不过最好使用apply
......但是保持简单并且不使用任何此类东西更好。)
我们任何人都可以通过读者宏来定义类似的内容,但我认为,如果你期望有人会阅读你的代码,那么做这样的事情并不是一个好主意。
实际上这种读者宏是你要求的语法糖。你现在拒绝自己的想法吗?每当你使用非传统的语法糖时,你可能会为你未来的代码阅读器做坏事。