S表达式列表,(文字)数据的向量?

时间:2010-12-12 16:38:11

标签: list vector coding-style clojure

当我需要一个文字来测试一个接受序列的函数时,我注意到我自己习惯使用向量比列表更频繁。

即。 :

(map inc [1 2 3])

但不是:

(map inc (list 1 2 3))

虽然它们都是正确的(第二个中的少数额外字符可以通过引用来解决)。

因此,我实际上只使用列表来构造s表达式,无论是手动还是宏。

没有考虑已经讨论过here的性能问题,您认为哪种编码风格更好?

我知道这是一个有点主观的问题,但我想到,也许我正在从我的非lisp语言经验中继承我的“代码和数据分离”思维模式。

2 个答案:

答案 0 :(得分:4)

当性能没有问题时,矢量文字通常比列表更受欢迎;首先,它们更容易打字,而且字符更少,但(可能)更重要的是:它们更容易阅读。 (更容易区分函数调用等)

事实上,我很确定从矢量文字中获取的易读性是他们在许多宏中实施的原因。

(let (a 1) a) ;; =>例外:let requires a vector for it's binding

(let [a 1] a) ;; => 1

答案 1 :(得分:3)

Clojure中的矢量模糊地表示“这是数据”。 letfn的绑定组就是数据。它是符号序列或符号 - 值对序列。

列表含糊地表示“这是一个函数或宏调用”。当你看到一个列表时,你会非常安全地假设该列表中的第一件事是可调用的,而列表中的其他东西都是它的参数。

有例外。您会在惯用代码中看到(ns foo (:use (bar baz)))(ns foo [:use [bar baz]])。不知道为什么Clojure除了Clojure在某些领域发展得非常迅速和半有机,并且还在不断增长。但这是一个很好的经验法则。

不需要引用向量,这是避免某些错误的好方法,特别是考虑到Clojure中的许多东西都可以作为函数调用。 (:foo :bar)不是两个关键字的列表,但它会进行编译,在关键字:foo上调用:bar作为关键字查找,评估为nil。没有办法搞砸[:foo :bar]。它始终是两个关键字的向量。

不必低估引用向量元素的好处。你想用列表写这个怎么样?

(let [x 123 y 456] 
  [[:foo x] [:bar y]])

一种方式非常冗长,以至于您的数据在list的林中丢失了。另一种方式是不必要的标点符号。

(let [x 123 y 456] 
  (list (list :foo x) (list :bar y)))

(let [x 123 y 456] 
  `((:foo ~x) (:bar ~y)))

由于[]{},Clojure可能不是其他Lisp方言的括号汤。虽然有些人不喜欢Clojure最终拥有的))])}),但我认为最好是在))))))))的长串中迷失自己。

“代码就是数据”并不意味着您的所有数据都必须看起来像您的所有代码,反之亦然。您可以在需要时访问代码作为数据,这通常在宏中很少。与此同时,如果您的数据不是代码,为什么它看起来像代码?一系列电话号码不是代码。它没有理由列入清单。

正如你所说,列表存在性能问题。