6

なぜこの Clojure コードは次のようになるのでしょうか。

user=> (map (constantly (println "Loop it.")) (range 0 3))

次の出力が生成されます。

Loop it.
(nil nil nil)

関数を 3 回評価することの副作用として、"Loop it" を 3 回出力することを期待しています。

4

3 に答える 3

9

constantlyその引数を複数回評価しません。これはマクロではなく関数であるため、引数はconstantly実行前に1回だけ評価されます。すべてconstantlyは、(評価された)引数を取り、呼び出されるたびに指定された値を返す関数を返すことです(前述したように、引数はconstantly実行される前にすでに評価されているため、何も再評価しません)。

範囲内のすべての要素を呼び出すだけ(println "Loop it")の場合は、それを。の代わりにマップする関数として渡す必要がありconstantlyます。実際には、評価された式ではなく、関数として渡す必要があることに注意してください。

于 2012-07-23T13:09:27.750 に答える
3

繰り返し使用し、ラムダ式を使用することで、意図に近い動作を得ることができます。

例えば:

(repeatedly 3 #(println "Loop it"))

REPL にいる場合を除き、これは adorunなどで囲む必要があります。repeatedly怠け者です。

于 2012-07-23T16:46:45.897 に答える
3

sepp2k が正しく指摘してconstantlyいるように、関数であるため、その引数は一度だけ評価されます。

ここで行っていることを達成するための慣用的な方法は、次を使用することdoseqです。

(doseq [i (range 0 3)]
  (println "Loop it."))

または、代わりdotimesに(この特定のケースでは、によって生成されたシーケンスを実際に使用していないため、もう少し簡潔で効率的ですrange):

(dotimes [i 3]
  (println "Loop it."))

これらのソリューションは両方とも非遅延です。これは、副作用のためにコードを実行するだけの場合に必要なことです。

于 2012-07-23T17:00:01.517 に答える