【发布时间】:2014-08-27 03:31:11
【问题描述】:
我想知道以下在使用序列时“观察”序列的方式是否正确。我已经阅读了以下 SO 答案,但我有点惊讶,因为我已经多次阅读“正确”的方法是使用惰性(因此即使它也明确地使你的序列变得惰性)不是),但是那里甚至没有提到 “懒惰”这个词:
How to implement the Observer Design Pattern in a pure functional way?
所以基本上我有一个惰性序列,我想保持这个惰性序列 100% 纯净,我不希望观察者将任何东西泄漏到那个惰性序列中。在我的示例中,我只是使用(range 100000),但任何惰性序列都可以。
然后我使用一些可变性(在 Clojure 中使用原子)做这样的事情(代码是可运行的,您可以在 REPL 中复制/粘贴):
(let [a (atom (range 100000))]
(loop [i 0]
(if (= 0 (mod i 10)) (println "i: " i)) ; the observer
(if (= 100 i)
(take 1 @a)
(do (reset! a (rest @a)) (recur (inc i))))))
重点不是我在这里使用了可变原子,而是惰性序列的实现根本不知道它正在被观察。观察者显然可以更花哨:就像实际通知观察者而不是使用副作用来打印 i(再一次:打印 i 这里只是一个例子)。
在使用惰性序列时,这是一种“正确”的观察方式吗?
如果这不正确,您在 Clojure 中使用惰性序列时会如何观察?
或者,您将如何在 Haskell 中执行此操作?
【问题讨论】:
-
鉴于 clojure 序列是不可变的,并且观察者模式旨在观察变化(序列不会发生这种情况),您究竟想观察什么?
-
@JoostDiepenmaat:正如我在问题中所写:我在消费序列时“走多远”。例如,假设我想对前 10 亿个素数求和,并显示一个进度条,说明我在计算过程中的进度(并更新进度条,例如,每 100 万个素数)。但是我不想修改我的惰性序列生成素数,因为“观察”的概念与素数的生成是正交的。我只是做了那个例子,但我需要不时做一些事情来“看看”发生了什么。我希望这是有道理的。
-
惰性序列甚至不需要是有限的:即使对于无限序列,更新 UI 以了解正在发生的事情也是有意义的。假设您正在通过分析(无限)素数惰性序列来寻找具有一些非常特定属性的素数,直到找到符合您的条件的素数:更新一次可能很方便,每 x i> 已测试的素数,UI,通过显示:"Tried xxx primes so far".
标签: haskell clojure observer-pattern lazy-evaluation