2024年Clojure状态调查!中分享您的想法。

欢迎!请查阅关于页面以了解更多关于如何使用本站的信息。

+1
命名空间和变量

我被任务转移到将一堆旧Lisp代码改编到21世纪。
我遇到了Clojure,并认为这可能是最佳途径。
我对Clojure来说是位新手。

Lisp代码广泛使用符号属性列表。
Clojure符号有属性列表吗?或者有类似属性列表的功能?

在Lisp中,我可以这样写

(put 'fly 'verb 'transitive) ; "fly"的动词属性是"transitive"。
--> 'transitive
(put 'fly 'noun '(a buzzing little bug)) ; "fly"的名词属性是"a buzzing little bug"
--> (a buzzing little bug)
(get 'fly 'verb) ; 展示"fly"的动词属性
--> transitive
(symbol-plist 'fly) ; 展示"fly"的所有属性
--> (verb transitive noun (a buzzing little bug))

Clojure支持符号属性列表吗?

2 个答案

+2

Clojure允许您将元数据(任意信息映射)附加到符号和其他对象(集合、变量等),这可能是一种类似的设施。在Clojure元数据中,您可以将动词和名词作为元数据附加到符号(使用关键字作为键更为惯例,但任何东西都可以)。我认为主要区别是您将具有不可变的值/元数据,而不是可变的。

(def f (with-meta 'fly {'verb 'transitive, 'noun '(a buzzing little bug)}))
(get (meta f) 'verb)
;;=> transitive
(meta f)
;;=> {verb transitive noun (a buzzing little bug)}

另请参阅

https://clojure.org/reference/metadata

+1

嗯,是的。属性列表的数据结构实质上是一个嵌套的映射(至少从我能够从您的示例中推断出的,我对原生属性列表并不十分熟悉)。哈希表在Clojure中是内置的,且易于使用。它们可以接受任何值作为键和值。

更不同的是,您给出的示例是可变的。这当然可以使用下面的`atom`实现,但Clojure的一个主要特点是进行可变操作在语法上可能有些笨拙。
然而,这里有一个如您描述的工作示例

(def db (atom {}))

(defn put [word prop value]
  (swap db assoc-in [word prop] value))

(defn get' [word prop]
  (get-in @db [word prop]))

(defn symbol-plist [word]
  (keys (get-in @db [word])))

另一件事是,人们通常使用`:keywords`而不是`'symbols'`,因为如果未引用,符号往往会以令人烦恼的方式尝试进行解析。对于列表也是如此。在字面数据结构中,更常见的是将集合作为向量(或集合)。

并且您在示例中创建的数据可以使用

{'fly {'noun '(a buzzing little bug)
       'verb 'transitive}}
  

这种数据结构是不可变的。symbol-plist等于(keys (get the-structure 'fly)),get是(get (get ... 'fly) 'verb)(get-in ... ['fly 'verb])

而put是(assoc-in ... ['fly 'adjective] 'nah-not-really)

但您需要保存引用,无论是在执行过程中的闭包中,如下所示

(let [db {'fly {'noun '(a buzzing little bug) 'verb 'transitive}}
      db (assoc-in db ['cat 'noun] '(a little furry animal))
      ...]
    db)

或者在第一个代码块中概述的atom中。

传统的方式是使用关键字(而不是符号)作为属性值,但这并不阻止您使用符号。

...