Clojure评估过程,读者的工作和直接传递数据结构到clojures编译器/评估器

时间:2014-05-27 20:22:36

标签: clojure

我对clojure的读者感到困惑。 reader's read函数传递的输入可以是源文件或直接键入REPL的一些ASCII文本。然后 reader 生成一个数据结构并将其传递给编译器,以便对其进行评估。

我不明白的是数据结构的外观如何'对于编译器?

read-string函数在传递字符串时与 reader read函数的功能相同。 read-string "(+ 1 2 3)")返回 (+ 1 2 3) 。这是否意味着(+ 1 2 3)是作为内部数据结构传递给编译器的确切表示?

为什么读者作为一个单独的功能,想法,阶段重要?为什么编译器没有将这些读取器表单序列化并在内部将其转换为数据结构?

另一个问题是:可以编写一个直接生成数据结构的程序,这样它们就可以直接传递给编译器(无需通过读取器阶段),也不能通过源文件中的宏编码。如何尝试这样做?

非常好的解释:What are the tasks of the "reader" during Lisp interpretation?

1 个答案:

答案 0 :(得分:3)

编译器不接收字符作为输入,它接收结构化的Clojure数据。编译器将符号解析为vars(通过在适当的命名空间中找到它们)。

让我们看一下您的read-string电话实际返回的内容:

user> (def input (read-string "(+ 1 2 3)"))
#'user/input
user> input
(+ 1 2 3)
user> (clojure.pprint/pprint (map (juxt identity type) input))
([+ clojure.lang.Symbol]
 [1 java.lang.Long]
 [2 java.lang.Long]
 [3 java.lang.Long])
nil

正如您所看到的,没有任何字符被发送到编译器 - 读取器将所有内容都缩减为原始Clojure类型(或多或少地由edn数据支持的类型),并且编译器将其转换为可运行的代码。

关于"直接生成这些数据结构",这正是宏所做的事情(尽管至少宏调用将由读者处理宏调用)。

user> (defmacro construct-addition [n] (list + 1 2 n))
#'user/construct-addition
user> (construct-addition 5)
8
user> (macroexpand '(construct-addition 5))
(#<core$_PLUS_ clojure.core$_PLUS_@190767cf> 1 2 5)