4

我正在阅读 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”?

4

2 回答 2

5

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

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

于 2012-09-26T15:59:07.860 回答
4
  1. 函数式语言中没有变量。实际上,您需要区分variablevalueidx它只是一个绑定到具体值的名称,你不能重新分配它(但你可以将它重新绑定到另一个值)。

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

于 2012-09-26T15:55:17.253 回答