在 Clojure 中使用 let/fn 匹配参数
Matching parameters with let/fn in Clojure
这是 Programming Clojure (2nd edition) 书中的示例代码,用于计算素数。
(def primes
(concat
[2 3 5 7]
(lazy-seq
(let [primes-from
(fn primes-from [n [f & r]]
(if (some #(zero? (rem n %))
(take-while #(<= (* % %) n) primes))
(recur (+ n f) r)
(lazy-seq (cons n (primes-from (+ n f) r)))))
wheel (cycle [2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2
6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6
2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10])]
(primes-from 11 wheel)))))
该代码具有定义局部函数的结构 primes-from
以在 let 形式中使用该函数。
(def primes
(concat
[2 3 5 7]
(lazy-seq
(let [primes-from (fn primes-from [n [f & r]] ... ]
(primes-from 11 wheel)))))
但是,我不确定第一个参数 11
和第二个参数 wheel
如何匹配到 [primes-from (fn primes-from [n [f & r]] ... ]
结构。
此外,我看不到 primes-from
参数如何定义匿名函数 (fn primes-from [n [f & r]]
。
关于这段代码有什么解释吗?
let
定义 primes-from
来引用用 fn
定义的函数。
第一次调用primes-from
时,11匹配n
,wheel
匹配[f & r]
。 wheel
指的是一个序列,而 [f & r]
期望一个序列——这就是方括号的意思。 f
("first") 将匹配序列中的第一个元素,第一次通过时为 2。 &
表示它后面的参数 r
("rest") 旨在匹配序列的整个其余部分(第一次从 4 开始)。
(cycle
定义了惰性序列,因此匹配 r
的内容不会完全展开。)
"primes-from" 在 (let [primes-from ...
和
需要 "primes-from" 个 (fn primes-from ...
个。第一个实例允许初始调用 primes
定义的最后一行中的函数。第二个实例允许在 fn
定义中间按名称递归调用函数。 "primes-from" 的最后一个实例还为函数提供了一个内部名称 属性,这在调试过程中可能会有帮助。
(请注意 fn
定义中有两个递归调用。第一个使用 recur
,第二个使用 primes-from
。两者都可以使用 primes-from
,但一般情况下最好使用 recur
,如果可能的话,因为它不使用堆栈,因此效率更高,并且可以避免 运行 内存不足。recur
只能在尾部使用位置,即当不需要对函数中的 returned 值进行进一步处理时。在第二种情况下不可能使用 recur
,因为 return 值将被提供到 cons
和 lazy-seq
.)
这是 Programming Clojure (2nd edition) 书中的示例代码,用于计算素数。
(def primes
(concat
[2 3 5 7]
(lazy-seq
(let [primes-from
(fn primes-from [n [f & r]]
(if (some #(zero? (rem n %))
(take-while #(<= (* % %) n) primes))
(recur (+ n f) r)
(lazy-seq (cons n (primes-from (+ n f) r)))))
wheel (cycle [2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2
6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6
2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10])]
(primes-from 11 wheel)))))
该代码具有定义局部函数的结构 primes-from
以在 let 形式中使用该函数。
(def primes
(concat
[2 3 5 7]
(lazy-seq
(let [primes-from (fn primes-from [n [f & r]] ... ]
(primes-from 11 wheel)))))
但是,我不确定第一个参数 11
和第二个参数 wheel
如何匹配到 [primes-from (fn primes-from [n [f & r]] ... ]
结构。
此外,我看不到 primes-from
参数如何定义匿名函数 (fn primes-from [n [f & r]]
。
关于这段代码有什么解释吗?
let
定义 primes-from
来引用用 fn
定义的函数。
第一次调用primes-from
时,11匹配n
,wheel
匹配[f & r]
。 wheel
指的是一个序列,而 [f & r]
期望一个序列——这就是方括号的意思。 f
("first") 将匹配序列中的第一个元素,第一次通过时为 2。 &
表示它后面的参数 r
("rest") 旨在匹配序列的整个其余部分(第一次从 4 开始)。
(cycle
定义了惰性序列,因此匹配 r
的内容不会完全展开。)
"primes-from" 在 (let [primes-from ...
和
需要 "primes-from" 个 (fn primes-from ...
个。第一个实例允许初始调用 primes
定义的最后一行中的函数。第二个实例允许在 fn
定义中间按名称递归调用函数。 "primes-from" 的最后一个实例还为函数提供了一个内部名称 属性,这在调试过程中可能会有帮助。
(请注意 fn
定义中有两个递归调用。第一个使用 recur
,第二个使用 primes-from
。两者都可以使用 primes-from
,但一般情况下最好使用 recur
,如果可能的话,因为它不使用堆栈,因此效率更高,并且可以避免 运行 内存不足。recur
只能在尾部使用位置,即当不需要对函数中的 returned 值进行进一步处理时。在第二种情况下不可能使用 recur
,因为 return 值将被提供到 cons
和 lazy-seq
.)