Mar*_*ark 2 lisp common-lisp reader-macro
由Doug Hoyte阅读的书"Let Over Lambda",我发现了以下对#.符号的描述,即read-macro:
使用COMMON LISP内置的基本读取宏是#.读取时间eval宏.此读取宏允许您将对象嵌入到您读取的无法序列化的表单中,但可以使用一些lisp代码创建.
它来自第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))
Run Code Online (Sandbox Code Playgroud)
接下来,作者演示了一些硬核技巧,用#宏创建变体.
因此,事实证明它#'也是某种读取宏,它通常在表示函数名称的符号之前使用.但这是否必要,他的工作到底是什么?
我可以在有#'或没有它的情况下为高阶函数添加符号:
CL-USER> (defun test nil t)
TEST
CL-USER> (funcall #'test)
T
CL-USER> (funcall 'test)
T
Run Code Online (Sandbox Code Playgroud)
取得同样的成功.
您可以通过两种方式调用函数的全局定义:
CL-USER> (defun test nil t)
TEST
CL-USER> (funcall #'test)
T
CL-USER> (funcall 'test)
T
Run Code Online (Sandbox Code Playgroud)
但看到这个:
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
Run Code Online (Sandbox Code Playgroud)
(funcall 'foo) 从符号中查找函数.
(funcall #'foo)从词法环境中调用函数.如果没有,则使用全局定义.
#'foo是一种简写符号(function foo).
CL-USER 19 > '#'foo
(FUNCTION FOO)
Run Code Online (Sandbox Code Playgroud)
与大多数语言不同,Common Lisp实际上没有解析器.它有一个被称为读者的词法分析器.阅读器使用单个字符并在表格中查找它们并调用那里找到的函数[1].在Lisp中,解析器在其他语言中扮演的角色由宏实现.
[1] http://www.lispworks.com/documentation/lw51/CLHS/Body/02_b.htm
例如,分号的读者会占用该行的其余部分,并将其作为注释丢弃.所以,例如,读者开放paren.调用递归读取列表元素的函数.因此,例如单引号递归读取单个表单然后将其包装在引号中.因此'(1 2 3)被读作(引用(1 2 3)).有一些这些关键的复杂令牌读取器.
[2] http://www.lispworks.com/documentation/lw51/CLHS/Body/02_d.htm
角色#\#提供了一个放置一系列额外读者行为的地方.哈希读者重复主读者的设计.它消耗另一个角色并在表格中查找并调用在那里找到的函数.这些中有很多[3].
[3] http://www.lispworks.com/documentation/lw51/CLHS/Body/02_dh.htm
因此,例如,我们有一个类似于读取向量的列表的读者,例如#(1 2 3).因此,例如,我们对单个字符,这样你可以输入一个分号,双引号,或周期作为一个读者#\;,#\"和#\. 分别.
要回答您的具体问题:引用的哈希读取器,例如#'foo,类似于常规引用的哈希读取器.它读取以下标记并将其包装在函数中.#'foo读作(函数foo).
可以修改阅读器表格以自定义语言.表中的条目称为读取器宏.这个名称往往会使人们感到困惑,因为它们与defmacro定义的宏完全不同.它们共同提供了所谓的"成长"语言的能力[4].
[4] http://www.catonmat.net/blog/growing-a-language-by-guy-steele/
| 归档时间: |
|
| 查看次数: |
294 次 |
| 最近记录: |