Clojure是不是比其他lisps不那么同质化?
我记得在Clojure for Lisp Programmers 视频中重复的一个说法是,早期 Lisp,尤其是 Common Lisp 的一个很大的弱点是太多地与 Lisp 的列表结构相结合,尤其是cons单元格。您可以在链接视频的 25 分钟标记处找到此声明的一次出现,但我确信我记得在该系列的其他地方听到过它。重要的是,在视频的同一点,我们看到了这张幻灯片,向我们展示了 Clojure 有许多其他数据结构,而不仅仅是老派的 Lispy 列表:
这让我很困扰。我对 Lisp 的了解非常有限,但我一直被告知,其传奇的元可编程性的一个关键要素是一切 - 是的,一切 - 都是一个列表,这是防止我们在尝试时遇到的那种错误的原因元程序其他语言。这是否意味着通过添加新的一流数据结构,Clojure 降低了其同象性,从而使其比其他 Lisp(例如 Common Lisp)更难元编程?
回答
是不是一切 - 是的,一切 - 都是一个列表
这对 Lisp 来说从来就不是真的
CL-USER 1 > (defun what-is-it? (thing)
(format t "~%~s is of type ~a.~%" thing (type-of thing))
(format t "It is ~:[not ~;~]a list.~%" (listp thing))
(values))
WHAT-IS-IT?
CL-USER 2 > (what-is-it? "hello world")
"hello world" is of type SIMPLE-TEXT-STRING.
It is not a list.
CL-USER 3 > (what-is-it? #2a((0 1) (2 3)))
#2A((0 1) (2 3)) is of type (SIMPLE-ARRAY T (2 2)).
It is not a list.
CL-USER 4 > (defstruct foo bar baz)
FOO
CL-USER 5 > (what-is-it? #S(foo :bar oops :baz zoom))
#S(FOO :BAR OOPS :BAZ ZOOM) is of type FOO.
It is not a list.
CL-USER 6 > (what-is-it? 23749287349723/840283423)
23749287349723/840283423 is of type RATIO.
It is not a list.
并且因为 Lisp 是一种可编程的编程语言,我们可以为非列表数据类型添加外部表示:
为 FRAME 类添加原始符号。
CL-USER 10 > (defclass frame () (slots))
#<STANDARD-CLASS FRAME 4210359BEB>
打印机:
CL-USER 11 > (defmethod print-object ((o frame) stream)
(format stream "[~{~A~^ ~}]"
(when (and (slot-boundp o 'slots)
(slot-value o 'slots))
(slot-value o 'slots))))
#<STANDARD-METHOD PRINT-OBJECT NIL (FRAME T) 40200011C3>
读者:
CL-USER 12 > (set-macro-character
#[
(lambda (stream char)
(let ((slots (read-delimited-list #] stream))
(o (make-instance 'frame)))
(when slots
(setf (slot-value o 'slots) slots))
o)))
T
CL-USER 13 > (set-syntax-from-char #] #))
T
现在我们可以读取/打印这些对象:
CL-USER 14 > [a b]
[A B]
CL-USER 15 > (what-is-it? [a b])
[A B] is of type FRAME.
It is not a list.
回答
让我们把“同质性”这个词分开。
- homo-,意思是“相同”
- 标志性的,这里的意思是“代表”
- -ity,意思是“有这种属性的东西”
使宏成为可能(或至少更容易)的特性是语言本身是用您用来表示其他对象的相同数据结构来表示的。请注意,这个词不是“单一主义”,也不是“一切都是列表”。由于 Clojure 使用与在运行时描述其他值相同的数据结构来描述其语法,因此没有理由声称它不是同像的。
有趣的是,我可能会说 Clojure 最不具有同形性的方式之一是它实际上与旧的 lisps 共享的一个特性:它使用符号来表示源代码。在其他 lisps 中,这是很自然的,因为符号用于许多其他事情。不过,Clojure 有关键字,它们更常用于在运行时为数据命名。符号很少使用;我什至会说它们的主要用途是表示源代码元素!但是 Clojure 用来表示源代码元素的所有其他特性也经常用于表示其他事物:序列、向量、映射、字符串、数字、关键字、偶尔的集合,以及我没有想到的其他一些小众东西现在。
- I don't think "the fewest" is a good takeaway. There's a reason nobody writes real programs (macros or not) in lambda calculus. The important thing is that source code is represented in a format that is easy to consume and produce if you are used to the non-macro part of the language.