Clojure的懒惰如何与Java / impure代码的调用交互? [英] How does Clojure's laziness interact with calls to Java/impure code?

查看:184
本文介绍了Clojure的懒惰如何与Java / impure代码的调用交互?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



Clojure评估不纯的代码(或调用Java)



似乎副作用+延迟序列可能导致奇怪的行为。






这是我们知道的导致这个问题:



Clojure有延迟序列:

  user => (取5(范围)); (范围)返回无限列表
(0 1 2 3 4)



<副作用和不纯的函数:

  user => (def value(println 5))
5; 5打印输出到屏幕
user => value
nil; 'value'被赋值nil

此外,Clojure可以调用Java对象,效果。
但是,副作用可能与延迟评估交互不佳:

  user => (def my-seq(map#(do(println%)%)(range)))
#'user / my-seq
user => (取5 my-seq)
(0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
0 1 2 3 4)

所以它返回前5个元素,但打印第一个31!



我假设如果调用side-effect Java对象的方法。






附带问题:




  • 是否由程序员注意并防止此类情况?(是?)

  • 除了序列,Clojure是否执行严格的评估?(是?)


解决方案

Clojure的惰性seqs块大约30项,所以小的开销进一步减少。这不是纯粹主义者的选择,而是实用的选择。请咨询Clojure的欢乐为一个普通的解决方案来实现一个元素在时间。



懒惰seqs不是一个完美的匹配不纯的函数,因为你遇到的原因。



Clojure也会严格评估,但是使用宏有些不同。 如果会自然保留评估。


We stumbled upon an issue in our code today, and couldn't answer this Clojure question:

Does Clojure evaluate impure code (or calls to Java code) strictly or lazily?

It seems that side-effects + lazy sequences can lead to strange behavior.


Here's what we know that led to the question:

Clojure has lazy sequences:

user=> (take 5 (range)) ; (range) returns an infinite list
(0 1 2 3 4)

And Clojure has side-effects and impure functions:

user=> (def value (println 5))
5                               ; 5 is printed out to screen
user=> value
nil                             ; 'value' is assigned nil

Also, Clojure can make calls to Java objects, which may include side-effects. However, side-effects may interact poorly with lazy evaluation:

user=> (def my-seq (map #(do (println %) %) (range)))
#'user/my-seq
user=> (take 5 my-seq)                               
(0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
0 1 2 3 4)

So it returned the first 5 elements, but printed the first 31!

I assume the same kinds of problems could occur if calling side-effecting methods on Java objects. This could make it really hard to reason about code and figure out what's going to happen.


Ancillary questions:

  • Is it up to the programmer to watch out for and prevent such situations? (Yes?)
  • Besides sequences, does Clojure perform strict evaluation? (Yes?)

解决方案

Clojure's lazy seqs chunk about 30 items so the little overhead is further reduced. It's not the purist's choice but a practical one. Consult "The Joy of Clojure" for an ordinary solution to realize one element at time.

Lazy seqs aren't a perfect match for impure functions for the reason you encountered.

Clojure will also evaluate strictly, but with macros things are a bit different. Builtins such as if will naturally hold evaluating.

这篇关于Clojure的懒惰如何与Java / impure代码的调用交互?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆