4

実現時に作成される接続の LazySeq があります。接続を作成しようとして例外が発生した場合は、LazySeq で既に実現されているすべての接続を反復処理して閉じたいと思います。何かのようなもの:

(try  
  (dorun connections)
  (catch ConnectException (close-connections connections)))

close-connectionsただし、接続を再度認識しようとするため、これはうまく機能しません。追加の接続を実現するのではなく、実現された接続のみを閉じたい。これを行うためのアイデアはありますか?

4

2 に答える 2

3

更新: この回答は元の質問で提示されたコンテキストで機能しますが(doallシーケンスを実行し、例外があった場合にどれが認識されたかを判断します)、いくつかの欠陥が含まれており、質問のタイトルで提案されている一般的な使用には適していません. ただし、Michał Marczyk の答えを理解するのに役立つかもしれない理論的 (ただし欠陥のある) 根拠を示しています。その答えを理解するのに苦労している場合、この答えは物事をもう少し分解することで役立つかもしれません. また、遭遇する可能性のあるいくつかの落とし穴も示しています。それ以外の場合は、この回答を無視してください。

LazySeqを実装しているため、理論的には、これは false を返すIPendingまで連続するテール シーケンスを反復するのと同じくらい簡単なはずです。realized?

(defn successive-tails [s]
  (take-while not-empty
              (iterate rest s)))

(defn take-realized [s]
  (map first
       (take-while realized?
                   (successive-tails s))))

さて、あなたが本当にLazySeq最初から最後まで100%持っているなら、それはそれです-実現されtake-realizedたアイテムを返します.s

編集:わかりました、そうではありません。これは、例外がスローされる前に実現されたアイテムを特定するために機能します。ただし、Michal Marcyzk が指摘するように、シーケンス内のすべての項目が別のコンテキストで実現されます。

その後、次のようにクリーンアップ ロジックを記述できます。

(try  
  (dorun connections) ; or doall
  (catch ConnectException (close-connections (take-realized connections))))

ただし、Clojure の「遅延」構造の多くは 100% 遅延ではないことに注意してください。たとえば、rangeは を返しLazySeqますが、ダウンし始めるrestと に変わりChunkedConsます。残念ながら、ChunkedConsは を実装しておらずIPending、これを呼び出すとrealized?例外がスローされます。これを回避するには、任意のシーケンスでaのままになるlazy-seqa を明示的に構築するために使用できます。LazySeqLazySeq

(defn lazify [s]
  (if (empty? s)
    nil
    (lazy-seq (cons (first s) (lazify (rest s))))))

編集: Michał Marczyk がコメントで指摘したように、基になるシーケンスが遅延して消費されることを保証するものでlazifyはありません。実際、以前は実現されていなかったアイテムが実現される可能性があります (ただし、例外は初回のみスローされるようです)。その唯一の目的は、呼び出しのrest結果が か のいずれnilかになることを保証することLazySeqです。つまり、以下の例を実行するには十分に機能しますが、YMMV.

ここで、とクリーンアップ コードの両方で同じ「遅延」シーケンスを使用すると、 を使用できるようになります。実現中に例外が発生した場合に、部分的なシーケンス (失敗の前の部分) を返す式を作成する方法を示す例を次に示します。doruntake-realize

(let [v (for [i (lazify (range 100))]
          (if (= i 10)
            (throw (new RuntimeException "Boo!"))
            i))]
  (try
    (doall v)
    (catch Exception _ (take-realized v))))
于 2013-12-03T07:53:05.137 に答える