为什么funcall没有语法糖?我们非常需要它。编写像(&#do-something arg0 arg1 arg2)这样的代码而不是(funcall do-something arg0 arg1 arg2),不是很棒吗?为什么不添加一些像Ruby's &:method notation这样的东西呢?语言中已经有什么东西了吗?
发布于 2014-07-01 20:17:44
语言中没有这样的内置函数;不过,您可以很容易地将函数分配给其他名称,并使用该名称。例如,如果你想使用&,你可以:
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在“短到可以写”和“足够长到可以描述”之间取得了适当的平衡。
为什么
没有语法糖?
在Common Lisp中,您可能会将宏称为“语法糖”,但在这里没有必要这样做。Funcall是一个函数,而不是一个特殊的表单或宏,所以很容易用另一个名字给它起别名,如上所示。大多数人不这样做的事实应该说明它是多么令人向往。
发布于 2014-07-01 20:45:02
funcall没有语法,因为我们不太需要它(否则,定义" we ")。我的意思是,在Lisp-2中,例如Common Lisp,这是一种权衡,除非您正在做一些繁重的lambda演算,否则您会习惯它。
如果您确实想使用更简洁的语法,可以定义一个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))检查编译器是否会优化传递给apply的lambda forms和dynamic-extent &rest参数。
我建议不要将单字符&定义为macro character,因为它是一个主要用于符号&optional, &rest, &key, &allow-other-keys, &aux, &whole, &body and &environment的constituent character。
发布于 2014-07-01 20:40:21
如果你倾向于使用黑魔法:
(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 ...但更好的做法是让事情变得简单,并且不使用这类东西。)
当然,我们任何人都可以通过阅读器宏来定义类似的东西,但我认为如果你希望有人在某个时候阅读你的代码,那么做这样的事情并不是一个很好的主意。
。
实际上,这种阅读器宏是你想要的语法糖。你现在拒绝你自己的想法了吗?每次,当您使用非常规语法糖时,您可能会使未来的代码阅读器的情况变得更糟。
https://stackoverflow.com/questions/24508641
复制相似问题