在Clojure中绑定结:没有(显式,丑陋)突变的循环引用? [英] Tying the knot in Clojure: circular references without (explicit, ugly) mutation?

查看:126
本文介绍了在Clojure中绑定结:没有(显式,丑陋)突变的循环引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的回答中,在 Clojure For Comprehension示例中,我有一个函数处理自己的输出:

 (defn stream [seed] 
(defn helper [slow]
concat(map#(str(first slow)%)seed)(lazy-seq(helper(rest slow))))​​
(声明延迟)
-seq delayed))]
(def delayed(helper slow))
delayed))

(取25(stream [abc]) )
(abcaaabacbabbbccacbccaaaaabaac
abaabbabcacaacbaccbaababbacbba)

它通过创建一个正向引用( delayed )来工作,它被用作延迟序列中的第二个条目 slow )。该序列被传递给函数,即lazy,并且该函数的输出(延迟序列的第一部分,不需要评估 delayed )然后用于设置延迟的值。



这样我就打结。但是在Haskell中这样做更加优雅(例如,绑定结的解释)。考虑到Clojure有 delay force ,我想知道是否有更好的方法来做上述? >

然后问题:在上面的代码中可以避免(丑陋,显式)突变(延迟)?显然(?)你还需要突变,但是它可以被懒惰的结构隐藏?



[昨天我有一个问题,试图理解如何做到这一点;没有人在上面的代码之前回复工作,所以我删除它,但我不是真的很高兴这种方法,所以我再试一次。]



另请参见:必须Clojure循环数据结构涉及如ref?

解决方案

我不确定我能否回答一般情况的问题,这个函数似乎解决了特定的情况。

 (defn stream 
[seed]
步骤(fn [prev](for [p prev s seed](str ps)))]
(for [x(iterate step seed)yx] y))

虽然我遇到了大量(dorun(take ...))的内存不足异常。所以这个功能可能有问题。


In my answer at Clojure For Comprehension example I have a function that processes its own output:

(defn stream [seed]
  (defn helper [slow]
    (concat (map #(str (first slow) %) seed) (lazy-seq (helper (rest slow)))))
  (declare delayed)
  (let [slow (cons "" (lazy-seq delayed))]
    (def delayed (helper slow))
    delayed))

(take 25 (stream ["a" "b" "c"]))
("a" "b" "c" "aa" "ab" "ac" "ba" "bb" "bc" "ca" "cb" "cc" "aaa" "aab" "aac" 
"aba" "abb" "abc" "aca" "acb" "acc" "baa" "bab" "bac" "bba")

It works by creating a forward reference (delayed) which is used as the second entry in a lazy sequence (slow). That sequence is passed to the function, which is lazy, and the output from that function (the very first part of the lazy sequence, which does not require the evaluation of delayed) is then used to set the value of delayed.

In this way I "tie the knot". But this is done much more elegantly in Haskell (eg. Explanation of "tying the knot"). Given that Clojure has delay and force, I wondered if there was a better way to do the above?

The question then: can the (ugly, explicit) mutation (of delayed) somehow be avoided in the code above? Obviously(?) you still need mutation, but can it be hidden by "lazy" constructs?

[I had a question last night with a similar title when I was still trying to understand how to do this; no one replied before the code above worked, so I deleted it, but I am not really happy with this approach so am trying again.]

See also: Must Clojure circular data structures involve constructs like ref? (kinda frustrating that people are duplicating questions).

解决方案

I'm not sure I can answer the question for the general case, but this function seems to solve the particular case.

(defn stream
  [seed]
  (let [step (fn [prev] (for [p prev s seed] (str p s)))]
    (for [x (iterate step seed) y x] y)))

Although I ran into a out of memory exception for a large (dorun (take ...)). So there probably is an issue with this function.

这篇关于在Clojure中绑定结:没有(显式,丑陋)突变的循环引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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