当我需要一个文字来测试一个接受序列的函数时,我注意到我自己习惯使用向量比列表更频繁。
即。 :
(map inc [1 2 3])
但不是:
(map inc (list 1 2 3))
虽然它们都是正确的(第二个中的少数额外字符可以通过引用来解决)。
因此,我实际上只使用列表来构造s表达式,无论是手动还是宏。
没有考虑已经讨论过here的性能问题,您认为哪种编码风格更好?
我知道这是一个有点主观的问题,但我想到,也许我正在从我的非lisp语言经验中继承我的“代码和数据分离”思维模式。
答案 0 :(得分:4)
当性能没有问题时,矢量文字通常比列表更受欢迎;首先,它们更容易打字,而且字符更少,但(可能)更重要的是:它们更容易阅读。 (更容易区分函数调用等)
事实上,我很确定从矢量文字中获取的易读性是他们在许多宏中实施的原因。
(let (a 1) a) ;; =>
例外:let requires a vector for it's binding
(let [a 1] a) ;; => 1
答案 1 :(得分:3)
Clojure中的矢量模糊地表示“这是数据”。 let
或fn
的绑定组就是数据。它是符号序列或符号 - 值对序列。
列表含糊地表示“这是一个函数或宏调用”。当你看到一个列表时,你会非常安全地假设该列表中的第一件事是可调用的,而列表中的其他东西都是它的参数。
有例外。您会在惯用代码中看到(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最终拥有的))])})
,但我认为最好是在))))))))
的长串中迷失自己。
“代码就是数据”并不意味着您的所有数据都必须看起来像您的所有代码,反之亦然。您可以在需要时访问代码作为数据,这通常在宏中很少。与此同时,如果您的数据不是代码,为什么它看起来像代码?一系列电话号码不是代码。它没有理由列入清单。
正如你所说,列表存在性能问题。