Java 我在clojure和println得到了bizzaro的行为

Java 我在clojure和println得到了bizzaro的行为,java,clojure,Java,Clojure,下面的代码正在创建我没有预料到的输出 (defn my-rand [] (let [r (rand-int 10)] (print "HI ") r)) (take 3 (repeatedly #(my-rand))) -> (HI HI 5 HI 5 4) (take 4 (repeatedly #(my-rand))) -> (HI HI 7 HI 0 HI 2 9) (take 5 (repeatedly #(my-rand))) -> (HI H

下面的代码正在创建我没有预料到的输出

(defn my-rand []
  (let [r (rand-int 10)]
    (print "HI ")
    r)) 

(take 3 (repeatedly #(my-rand))) -> (HI HI 5 HI 5 4)
(take 4 (repeatedly #(my-rand))) -> (HI HI 7 HI 0 HI 2 9)
(take 5 (repeatedly #(my-rand))) -> (HI HI 4 HI 2 HI 4 HI 3 2)
(take 6 (repeatedly #(my-rand))) -> (HI HI 7 HI 6 HI 5 HI 6 HI 2 6)

(my-rand) -> 7 | stdout: HI

我觉得奇怪的是,take…反复制作了两个连续的HIs。我还注意到最后生产的两个产品都是r。另外,有趣的是,take…反复调用在stdout上没有产生任何输出。这是为什么?

REPL以其三个阶段的功能命名:读取、评估、打印循环

我的rand只返回整数

repl隐式地将结果打印为来自重复的结果列表。同时,my rand中的println语句生成它们的输出。之所以会发生交错,是因为除非实现某种锁定,否则多个函数的输出是不可预测的,并且没有保证的顺序。

都会获取并重复生成惰性序列。因此,重复3次,我的rand不会调用我的rand,除非序列实现,即当它被遍历时。所以,如果您从未对生成的seq执行任何操作,则在stdout上不会看到任何内容

正如noisesmith指出的,如果您在REPL中,REPL将打印您给它的表达式返回的值。在这个花瓶中,反复取3,我的兰特将生成一个未实现的懒序列。然后REPL将打印该seq。print函数在seq上迭代,并加上一点格式设置,打印seq的每个元素。由于seq之前未实现,因此需要在打印之前实现这些元素。现在,实现一个元素意味着调用我的rand,它反过来调用print。因此,我的rand中的print调用与每个元素的打印交织在一起


考虑到我们有一个懒惰的seq,我可以理解为什么看到他的两个seq连成一行会令人惊讶。毕竟假设之前没有实现任何元素,因为元素一次打印一个,我们不应该在每个元素之前看到一个HI吗?正如amalloy在对noisesmith的回答的评论中所暗示的那样,为了确定惰性seq是否有下一个元素,必须实现下一个元素(如果存在)。显然,该确定是在打印当前元素之前进行的。结果,前两个元素在第一个元素打印之前实现。因此,这两个人是他的。但是,对于后续元素,当前元素已经实现,以便打印上一个元素,因此,如果需要在该点实现下一个元素,则只需实现下一个元素。

锁定在这里并不真正相关:只涉及一个线程,它将始终以相同的顺序打印内容。然而,我认为你是对的,因为REPL的print函数没有任何特定的契约需要满足,所以不能保证这种情况会发生。碰巧,它似乎调用了next s,实现了s的两个元素,以便决定如何打印s的第一个元素。defn my rand[]让[r rand int 10]打印修复它的HI r。您正在返回一个要打印号码的号码。