Clojure序列理解中是否存在变量?

时间:2012-09-26 15:26:44

标签: clojure list-comprehension for-comprehension

我正在阅读Programming Clojure第2版,第49页它涵盖了Clojure的for循环结构,它实际上是一个序列理解。

作者建议使用以下代码:

(defn indexed [coll] (map-indexed vector coll))

(defn index-filter [pred col]
  (when pred
    (for [[idx elt] (indexed col) :when (pred elt)] idx)))

(index-filter #{\a} "aba")
(0 2)

...优于基于Java的命令式示例,并且给出的证据是“通过使用高阶函数......任何函数索引都避免了对变量的所有需求。”

什么是“idx”,“elt”,如果它们不是变量?它们是指除累加器之外的变量吗?

另外,为什么#{\ a}而不是“a”?

2 个答案:

答案 0 :(得分:5)

pred函数 - #{\a}是包含字符a的集合。在Clojure中,set是一个函数,如果它包含参数\a,则返回true。您还可以使用#(= % \a)(fn [x] (= \a x))

正如另一个答案所暗示的那样,“在制作这个例子时没有创造任何国家。” idxelt的函数类似于变量,但只对for序列理解是局部的,所以代码更紧凑,没有状态,并且可以说更清晰(一旦你习惯了序列理解,至少:-)) - 也许文本在这一点上并不是最清晰的。

答案 1 :(得分:4)

  1. 功能语言中没有变量。实际上,您需要区分 变量 idx它只是一个与具体价值绑定的名称,你无法重新分配它(但你可以将它反弹到另一个值)。

  2. 函数index-filter的第一个参数是谓词,表示返回truefalse的函数。 #{\a}它是一个数据结构set,但也可以像处理函数一样对待。如果将元素作为参数传递给set函数,则返回此参数(如 true ),如果元素存在,则返回nil(如 false )。因此,您可以将此set谓词视为以更易理解的方式编写的匿名函数#(contains? #{\a} %)