Clojure是否比其他Lisp方言更少的具有同像性?

7

我记得在Clojure for Lisp Programmers videos中反复提到的一种说法是早期Lisps,特别是Common Lisp,太多东西与Lisps的列表结构结合在一起,特别是cons单元。您可以在链接视频的25分钟标记处找到这种说法的一个发生,但我确信我记得在系列其他地方也听过它。重要的是,在视频的同一点上,我们看到了这张幻灯片,向我们展示了Clojure不仅有老派Lispy列表,还有许多其他数据结构: enter image description here 这让我感到不安。我对Lisp的了解非常有限,但我一直被告知其传奇性元编程的关键元素是每个东西 - 是的,每个东西 - 都是一个列表,这就是防止我们在尝试元编程其他语言时遇到的错误的原因。这是否意味着通过添加新的一流数据结构,Clojure减少了其同像性,从而使它比其他Lisp(如Common Lisp)更难进行元编程?

1
这是一个基于观点的问题的典型例子。应该将其关闭:这是一个好问题,但不适合在SO上讨论。 - user5920214
1
@tfb 你不认为同像性是一个可衡量的量吗? - J. Mini
同构性只有一个位:即一种语言的源代码是否可以作为该语言中的(预定义)数据结构进行处理,其他一切都是观点。 - user5920214
1
Clojure与Lisp相差甚远;它是一种特定领域的语言,用于操作不可变的、持久化的序列,受到Lisp语法的启发,并且在元编程概念上进行了实质性的修改。 - Kaz
元编程的唯一要求始终是能够在编译时构造抽象语法树(AST)。AST可以是任何东西,不一定是仅仅由 cons 单元格堆叠而成。例如,Scheme 的“语法对象”根本就不是列表。你可以将它们转换为列表,但这样做并不是一个好主意,因为你会失去位置元数据。 - SK-logic
4个回答

12

一切,完全的一切,都是列表

但对于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.

1
"Lisp 中的一切都是列表" 实际上比同样流行的 "Haskell 中的一切都是函数" 更加错误。 - amalloy

9
让我们分解一下“同像性”这个词。
- “homo-”,意思是“相同的” - “iconic”,这里的意思是“由……表示” - “-ity”,意思是“具有这种属性的东西”
使宏成为可能(或至少更容易)的特质是语言本身用于表示其他对象的数据结构与之相同。请注意,这个词不是“单列表主义”或“一切皆列表”。由于Clojure使用相同的数据结构来描述其语法和运行时的其他值,因此没有理由声称它不是同像的。
有趣的是,我可能会说Clojure最不同像的一种方式是它实际上与旧的Lisp共享的一种特征:它使用符号来表示源代码。 在其他Lisp中,这非常自然,因为符号用于许多其他事情。 但是Clojure有关键字,它们在运行时更常用于为数据命名。 符号很少被使用; 我甚至可以说,它们的主要用途是表示源代码元素! 但是Clojure用于表示源代码元素的所有其他功能也经常用于表示其他东西:序列、向量、映射、字符串、数字、关键字、偶尔的集合,以及可能是我现在没有想到的其他一些小众功能。

因此,数据结构和对象的表示越少,编写宏就越容易。Clojure之所以独特,并不仅仅因为它使用符号,而是因为它可以同时处理符号和关键字。Clojure将源代码和常用数据结构使用相同的符号。我理解的对吗?我只用过宏(昨天才恍然大悟->>的含义),但我很期待有一天能学会编写自己的宏 :) - Aaron Bell
2
我认为“最少”的结论并不好。没有人会用λ演算写真正的程序(无论是宏还是非宏)。重要的是,源代码以易于消费和生成的格式表示,如果您习惯于语言的非宏部分,则更容易理解和编写。 - amalloy
如果您列出一种语言的所有基本构造机制,并计算其中有多少是同像的,然后将该数字除以列表中的总项目数,那么您将得到一个描述该语言同像性的百分比,即其特征同像性。我认为这个问题试图询问的就是这个。换句话说,如果一个前缀Lisp语言中有100个语言特性,其中一个是中缀整数表达式,那么该语言的最大同像性为99%。 - MicroservicesOnDDD

2
在Clojure中,除了列表之外,唯一需要一些语言结构的额外数据结构是向量,它们通常位于函数参数序列或let符号/表达式对等周围。所有这些都可以用于数据字面量,但与函数调用和宏调用相比,数据字面量在编写Clojure宏时使用较少。
我不知道Clojure中是否有任何东西会使编写宏比在Common Lisp中更困难,而有一些Clojure特有的功能可以使其变得稍微容易一些,例如Clojure回引用表达式默认会命名空间限定符号的行为,这通常是您想要防止意外“捕获”名称的情况。

就编程而言,FWIW关键字和映射通常用于语言结构,最突出的是元数据。 - amalloy

2
正如之前的回答者所指出的那样,“同像性”仅意味着著名的“代码数据”:即编程语言的代码由该语言的数据结构100%组成,因此可以使用语言中通常用于操作数据结构的函数轻松地进行构建和操作。
由于Clojure数据结构包括列表、向量、映射...(您列出的那些),而Clojure代码由列表、向量、映射...组成,因此Clojure代码是同像的。
Common Lisp和其他Lisp也是如此。
Common Lisp也包含列表、向量、哈希表等。 但是,Common Lisp的代码比Clojure更严格地遵循列表(函数参数在参数列表中而不是像Clojure中那样在向量中)。 因此,您可以更一致地使用函数来操纵列表以进行元编程目的(宏)。
这是否比Clojure更具“同像性”是一个哲学问题。 但是,对于代码的操作,你肯定需要比在Clojure中更少的函数集。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接