クロージャーの怠惰の地図

私はClojureで簡単なGUIを構築しています。私は、letのコンテキストでmapを使用して、複数のGUIコンポーネントに単一の関数を適用しようとしています。

(マップ#(f%コンポーネント4)[コンポーネント1コンポーネント2コンポーネント3])

コンポーネントはすべてletで定義されています。

問題は、マップが怠惰で、アクションがコンポーネントに適用されていないことですが、私はそれを 'take'にラップして強制することができます。

マップするための怠惰な代替手段はありますか?それとも私はこれについて別のことをするべきですか?

編集: 日食で反時計回りに使用。私は、REPLから( 'Lib:reload'を使用して)エディタからCTRL + Enterを使用して異なる結果を得ました。リロードするとGUIが起動しますが、上記の問題が発生します。エディタからCTRL + Enterを使用しても問題は発生しませんでした。したがって、問題の記述が不正確かもしれません。いずれにせよ、このシナリオでは、doseqがマップの代わりになるようです。

6

3 答え

私は、 take を取っても何の違いもないというあなたの主張に挑戦します。 doall または dorun でラップした場合、必要な処理が行われますが、 map の代わりにこの種の副作用のみのアクションのためのコード>。

注意

もともと質問にコメントとして投稿されました。人気のある需要によって答えにコピーされています。

17
追加された
私は従わない。あなたがすべての要素を取るなら、あなたはそれらの実現を強制しないのですか?私はdoallなどは良くないと主張していないが、おそらく3を取ることもできるだろうか?
追加された 著者 Adrian Mouat,
ああ!私は決してそれを知らなかったが、実際には:(最初の(10000を取るmap#do(Thread/sleep 10)%(range)))))非常に迅速に戻ります。
追加された 著者 Adrian Mouat,
私はなぜそれが睡眠のためのより高い値と(tryclj.comの)タイムアウトしたのだろうかと思った。ありがとう、私は今朝たくさんのことを学んだ:)
追加された 著者 Adrian Mouat,
take はそれ自体が怠惰です。
追加された 著者 kotarak,
@AdrianMouat範囲とマップの両方が効率のためにチャンクされているので、実際には32要素を実現します。そのため、0.32秒かかります。しかし、(最初の10000(map#do(Thread/sleep 10)%)(repeat 1))))は0.01秒で期待どおりに戻ります。
追加された 著者 amalloy,

doseq is probably the best way to approach this. doseq is roughly equivalent to a "for-each" statement that loops over each element of a collection in many other languages. It is guaranteed to be non-lazy.

(doseq 
  [comp [component1 component2 component3]]
  (f comp component4))

いくつかの一般的なアドバイス:

  • Use map and its lazy friends (including take, drop etc.) when you want a sequence as an output
  • Use doseq, doall, dotimes etc. when you are more interested in the side effects
8
追加された
親指のルール:副作用?名前に do を探します。
追加された 著者 kotarak,

あなたのマップをdoallで囲むと、評価が強制されます。より良い選択肢は、副作用を伴うものに使用されるdoseqです。

2
追加された
ありがとう、これはうまくいきました。構文は、私がやろうとしていたことに対してもうまく機能します。
追加された 著者 user1064799,