lisp - 使用# a.k.a. 读取宏

标签 lisp common-lisp reader-macro

阅读 Doug Hoyte 的书“Let Over Lambda”,我发现了以下对 #. 符号的描述,也就是 read-macro:

A basic read macro that comes built in with COMMON LISP is the #. read-time eval macro. This read macro lets you embed objects into the forms you read that can't be serialised, but can be created with a bit of lisp code.

它来自第 4 章,本书的大部分内容可以在这里找到: http://letoverlambda.com/index.cl/toc

这是书中的一个例子,展示了同一个表达式每次读起来可能有何不同:

* '(football-game
     (game-started-at
       #.(get-internal-real-time))
     (coin-flip
       #.(if (zerop (random 2)) 'heads 'tails)))

(FOOTBALL-GAME
  (GAME-STARTED-AT 187)
  (COIN-FLIP HEADS))

* '(football-game
     (game-started-at
       #.(get-internal-real-time))
     (coin-flip
   #.(if (zerop (random 2)) 'heads 'tails)))

(FOOTBALL-GAME
  (GAME-STARTED-AT 309)
  (COIN-FLIP TAILS))

接下来,作者演示了一些核心技巧,使用 # 宏创建变体。

所以,原来#'也是某种阅读宏,它通常用在表示函数名称的符号之前。但这是否有必要,他在那里的工作到底是什么?

我可以用 #' 或不用它来为高阶函数放置符号:

CL-USER> (defun test nil t)
TEST
CL-USER> (funcall #'test)
T
CL-USER> (funcall 'test)
T

同样成功。

最佳答案

您可以通过两种方式调用函数的全局定义:

CL-USER> (defun test nil t)
TEST
CL-USER> (funcall #'test)
T
CL-USER> (funcall 'test)
T

但是看到这个:

CL-USER 10 > (defun foo () 42)
FOO

CL-USER 11 > (flet ((foo () 82))
               (print (foo))
               (print (funcall 'foo))
               (print (funcall #'foo)))

82   ; the local definition
42   ; the symbol references the global definition
82   ; (function foo) / #'foo  references the local definition

(funcall 'foo) 从符号中查找函数。

(funcall #'foo) 从词法环境调用函数。如果没有,则使用全局定义。

#'foo(function foo) 的简写符号。

CL-USER 19 > '#'foo
(FUNCTION FOO)

关于lisp - 使用# a.k.a. 读取宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23977617/

相关文章:

lisp - Lisp 中的赋值

lisp - 使用宏弹出列表中的第一个元素

macros - 如何在普通 lisp 中编写宏定义宏

common-lisp - Sharpsign Colon 和 Gensym 之间的差异

common-lisp - 我可以在他们的扩展站点中获取宏的边界吗?

lisp - #+: and #-: in common lisp是什么意思

scheme - If 和 cond 作为特殊形式

c - LISP 算术实现

scheme - 将列表的元素配对在一起

Lisp:尝试使用 acons 和循环生成 a-list 时出现 APPLY 错误