用于funcall的语法糖?

时间:2014-07-01 11:02:23

标签: functional-programming lisp common-lisp

为什么funcall没有语法糖?我们需要它很多。写(&#do-something arg0 arg1 arg2)而不是(funcall do-something arg0 arg1 arg2)之类的东西真是太棒了。为什么不添加像Ruby&#;;方法符号这样的东西?该语言中是否有某些内容?

3 个答案:

答案 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 formsdynamic-extentapply &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 ......但是保持简单并且不使用任何此类东西更好。)

  

我们任何人都可以通过读者宏来定义类似的内容,但我认为,如果你期望有人会阅读你的代码,那么做这样的事情并不是一个好主意。

实际上这种读者宏是你要求的语法糖。你现在拒绝自己的想法吗?每当你使用非传统的语法糖时,你可能会为你未来的代码阅读器做坏事。