Clojure是否适用于无法实现惰性序列的前四个元素? [英] Clojure apply that does not realize the first four elements of a lazy sequence?
问题描述
apply强制给定一个惰性序列来实现四个元素。
It appears that apply forces the realization of four elements given a lazy sequence.
(take 1
(apply concat
(repeatedly #(do
(println "called")
(range 1 10)))))
=> "called"
=> "called"
=> "called"
=> "called"
是否有一种方法可以避免这种行为?
Is there a way to do an apply which does not behave this way?
谢谢
推荐答案
有办法吗?做一个
apply
不会这样的行为?
我认为简短的答案是:并非没有重新实现Clojure的一些基本功能。 apply
的实现直接依赖于Clojure的可调用函数的实现,并尝试发现给定函数对 .invoke $ c的正确处理。 $ c>通过枚举参数的输入序列。
I think the short answer is: not without reimplementing some of Clojure's basic functionality. apply
's implementation relies directly on Clojure's implementation of callable functions, and tries to discover the proper arity of the given function to .invoke
by enumerating the input sequence of arguments.
使用函数而不是懒散的,未分块的序列/化简器/换能器,而不是分解函数,可能会更容易分解您的解决方案在 apply
中使用可变参数函数。例如,这是使用换能器重新实现的示例,它仅调用一次body函数(每个长度 range
):
It may be easier to factor your solution using functions over lazy, un-chunked sequences / reducers / transducers, rather than using variadic functions with apply
. For example, here's your sample reimplemented with transducers and it only invokes the body function once (per length of range
):
(sequence
(comp
(mapcat identity)
(take 1))
(repeatedly #(do
(println "called")
(range 1 10))))
;; called
;; => (1)
使用 apply $ c来查看示例中的情况
, concat
, seq
, LazySeq
,等等:
-
反复
返回新的LazySeq
实例:(惰性序列(cons(f)(重复为f)))
。 - 对于给定2-arity
(apply concat< args>)
,apply
调用RT.seq
放在其参数列表中,对于LazySeq
然后调用LazySeq.seq
,它将调用您的函数 -
apply
然后调用Java impl。方法applyToHelper
尝试获取参数序列的长度。applyToHelper
尝试使用RT.boundedLength
(内部调用)确定参数列表的长度。接下来
,然后依次是seq
,因此它可以找到要正确调用IFn.invoke
重载 -
concat
本身又增加了lazy-seq
行为的另一层。 li>
repeatedly
returns a newLazySeq
instance:(lazy-seq (cons (f) (repeatedly f)))
.- For the given 2-arity
(apply concat <args>)
,apply
callsRT.seq
on its argument list, which for aLazySeq
then invokesLazySeq.seq
, which will invoke your function apply
then calls a Java impl. methodapplyToHelper
which tries to get the length of the argument sequence.applyToHelper
tries to determine the length of the argument list usingRT.boundedLength
, which internally callsnext
and in turnseq
, so it can find the proper overload ofIFn.invoke
to callconcat
itself adds another layer oflazy-seq
behavior.
您可以看到以下调用的堆栈跟踪:
You can see the stack traces of these invocations like this:
(take 1
(repeatedly #(do
(clojure.stacktrace/print-stack-trace (Exception.))
(range 1 10))))
第一条轨迹来自 apply
'最初对 seq
的调用,以及随后来自 RT.boundedLength
的跟踪。
The first trace descends from the apply
's initial call to seq
, and the subsequent traces from RT.boundedLength
.
这篇关于Clojure是否适用于无法实现惰性序列的前四个元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!