首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >funcall的语法糖?

funcall的语法糖?
EN

Stack Overflow用户
提问于 2014-07-01 19:02:23
回答 3查看 463关注 0票数 3

为什么funcall没有语法糖?我们非常需要它。编写像(&#do-something arg0 arg1 arg2)这样的代码而不是(funcall do-something arg0 arg1 arg2),不是很棒吗?为什么不添加一些像Ruby's &:method notation这样的东西呢?语言中已经有什么东西了吗?

EN

回答 3

Stack Overflow用户

发布于 2014-07-01 20:17:44

语言中没有这样的内置函数;不过,您可以很容易地将函数分配给其他名称,并使用该名称。例如,如果你想使用&,你可以:

代码语言:javascript
复制
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是一个函数,而不是一个特殊的表单或宏,所以很容易用另一个名字给它起别名,如上所示。大多数人不这样做的事实应该说明它是多么令人向往。

票数 9
EN

Stack Overflow用户

发布于 2014-07-01 20:45:02

funcall没有语法,因为我们不太需要它(否则,定义" we ")。我的意思是,在Lisp-2中,例如Common Lisp,这是一种权衡,除非您正在做一些繁重的lambda演算,否则您会习惯它。

如果您确实想使用更简洁的语法,可以定义一个dispatch macro character

代码语言:javascript
复制
(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))

检查编译器是否会优化传递给applylambda formsdynamic-extent &rest参数。

我建议不要将单字符&定义为macro character,因为它是一个主要用于符号&optional, &rest, &key, &allow-other-keys, &aux, &whole, &body and &environmentconstituent character

票数 8
EN

Stack Overflow用户

发布于 2014-07-01 20:40:21

如果你倾向于使用黑魔法:

代码语言:javascript
复制
(defun black-magic (stream sub-char numarg)
  (declare (ignore sub-char numarg))
  `(funcall ,@(read stream)))

(set-dispatch-macro-character
  #\# #\! #'black-magic)

粗略的例子:

代码语言:javascript
复制
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 ...但更好的做法是让事情变得简单,并且不使用这类东西。)

当然,我们任何人都可以通过阅读器宏来定义类似的东西,但我认为如果你希望有人在某个时候阅读你的代码,那么做这样的事情并不是一个很好的主意。

实际上,这种阅读器宏是你想要的语法糖。你现在拒绝你自己的想法了吗?每次,当您使用非常规语法糖时,您可能会使未来的代码阅读器的情况变得更糟。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24508641

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档