2

在回答有关使用相同参数(A:juxt)映射多个函数的函数的问题时,我想出了一个与 juxt 基本采用相同形式但使用 map 的函数:

(defn could-be-lazy-juxt
  [& funs]
  (fn [& args]
    (map apply funs (repeat args))))

=> ((juxt inc dec str) 1)
[2 0 "1"]
=> ((could-be-lazy-juxt inc dec str) 1)
(2 0 "1")

=> ((juxt * / -) 6 2)
[12 3 4]
=> ((could-be-lazy-juxt * / -) 6 2)
(12 3 4)

我对它的懒惰或性能一无所知,但 REPL 中的时间确实表明正在发生一些懒惰的事情。

=> (time (apply (juxt + -) (range 1 100)))
"Elapsed time: 0.097198 msecs"
[4950 -4948]
=> (time (apply (could-be-lazy-juxt + -) (range 1 100)))
"Elapsed time: 0.074558 msecs"
(4950 -4948)

=> (time (apply (juxt + -) (range 10000000)))
"Elapsed time: 1019.317913 msecs"
[49999995000000 -49999995000000]
=> (time (apply (could-be-lazy-juxt + -) (range 10000000)))
"Elapsed time: 0.070332 msecs"
(49999995000000 -49999995000000)

我确信这个功能并不是那么快(结果的打印“感觉”在两者中都一样长)。对函数执行 'take x' 只会限制评估函数的数量,这可能会限制其适用性,并且通过 'take' 限制其他参数在正常并列中应该同样懒惰。

这并列真的很懒吗?惰性并列是否会给表格带来任何有用的东西,例如作为其他惰性函数之间的合成步骤?性能(内存/cpu/对象计数/编译)有什么影响?为什么 Clojure juxt 用 reduce 实现并返回一个向量,这打破了惰性?

4

1 回答 1

1

是的,你的 juxt 实现是懒惰的,因为它只调用了懒惰的 map。

在没有意识到调用者中的参数的情况下很难以现在的形式调用它(通过使用apply。所以我对其进行了一些更改以获取一系列函数:

user> (defn could-be-lazy-juxt
  [funs]
  (fn [& args]
    (map #(apply %1 %2) funs (repeat args))))
#'user/could-be-lazy-juxt

然后定义一个惰性函数序列,当它实现时会产生大量输出

user> (defn loud-seq [len] (take len (map #(do (println "produced a function") %) (cycle [inc dec]))))
#'user/loud-seq

然后使用 juxt 从这个惰性函数序列中创建一个函数

user> (def f (could-be-lazy-juxt (loud-seq 50)))
#'user/f

如您所见,列表仍然是惰性的,它在调用结果函数时实现了它的函数列表。

所以让我们称之为:

user> (f 1)
(produced a function
produced a function
2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 produced a function
produced a function
0 2 0)
user> 

我把这样做的原因留给你;)

于 2012-04-06T23:12:58.153 回答