我正在阅读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”?
答案 0 :(得分:5)
pred
是函数 - #{\a}
是包含字符a的集合。在Clojure中,set是一个函数,如果它包含参数\a
,则返回true。您还可以使用#(= % \a)
或(fn [x] (= \a x))
。
正如另一个答案所暗示的那样,“在制作这个例子时没有创造任何国家。” idx
和elt
的函数类似于变量,但只对for
序列理解是局部的,所以代码更紧凑,没有状态,并且可以说更清晰(一旦你习惯了序列理解,至少:-)) - 也许文本在这一点上并不是最清晰的。
答案 1 :(得分:4)
功能语言中没有变量。实际上,您需要区分 变量 和 值 。 idx
它只是一个与具体价值绑定的名称,你无法重新分配它(但你可以将它反弹到另一个值)。
函数index-filter
的第一个参数是谓词,表示返回true
或false
的函数。 #{\a}
它是一个数据结构set
,但也可以像处理函数一样对待。如果将元素作为参数传递给set函数,则返回此参数(如 true ),如果元素存在,则返回nil(如 false )。因此,您可以将此set谓词视为以更易理解的方式编写的匿名函数#(contains? #{\a} %)