【问题标题】:Why is the class of '@foo Cons rather than PersistentList when inside a def?为什么在 def 中是 '@foo Cons 类而不是 PersistentList?
【发布时间】:2021-10-09 22:05:34
【问题描述】:

Clojure repl 下的快速实验:

> (class '@foo)
clojure.lang.PersistentList

这或多或少是意料之中的,所以让我们将相同的表达式包装在 def 中:

> (def x '@foo)
> (class x)
clojure.lang.Cons

我尝试使用def 和其他各种形式,但'@foo 似乎是唯一触发这种行为的形式。

【问题讨论】:

    标签: clojure


    【解决方案1】:

    我在新的 REPL 中尝试了这个并重现了该行为。

    对于您所看到的具体行为,有一个令人费解的解释。您在 Clojure 阅读器中发现了一个特殊的角落。

    @ 字符是“阅读器宏”,是以下内容的简写:

    @xxx  =>  (deref xxx)
    

    ' 字符是另一个阅读器宏,也是以下的简写:

    'yyy  => (quote yyy)
    

    把它们放在一起,你就得到了

    '@zzz  =>  (quote (deref zzz))
    

    所以quote 特殊形式首先出现。它说,“将这里包含的所有内容视为数据结构,而不是可执行代码”。

    数据结构(deref zzz)是一个包含两个符号derefzzz的列表。


    关于文字和 Var 之间的 class 的区别,我们看到:

    user=> (def bbb '@foo)
    #'user/bbb
    user=> (class bbb)
    clojure.lang.Cons
    
    user=> (def ccc (quote (deref foo)))
    #'user/ccc
    user=> (class ccc)
    clojure.lang.PersistentList
    

    使用“面向对象”的术语,ConsPersistentListPersistentVectorLazySeq 都是 Clojure 中通用“Seq”类型的“子类”。它们都可以互换使用,上面 2 个类的意外差异是一个不重要的实现细节。

    【讨论】:

    • 虽然它是一个未指定的实现细节,但我很好奇它是如何不同的。我原以为'x(quote x) 在所有情况下都是相同的。您是否碰巧发现了实现的什么怪癖使它以这种方式运行? (顺便说一句:向量不是序列。将其评估为向量是不正确的)
    猜你喜欢
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    • 2017-03-27
    • 2021-04-19
    • 2012-12-15
    • 2016-05-16
    相关资源
    最近更新 更多