30903


OCamlのライブラリExtLibの中のEnumについて質問します。

以下を実行しました。

[code]

    open Printf
    
    let tee f e =
      let e' = Enum.clone e in
      f e';
      e
    
    let term e =
      Enum.iter (fun _ -> ()) e
    
    let f e =
      Enum.map
        (fun inp ->
           let out = inp * 2 in
           printf "in f\t%d\t%d\n" inp out;
           out)
        e
    
    let () =
      let e = Enum.init 5 (fun i -> i) in
    
      e
      |> f
      |> tee
           (fun e ->
              Enum.iter (printf "in tee\t%d\n") e)
      |> term
    
[/code]

結果は以下です。

[code]

    in f    0   0
    in tee  0
    in f    1   2
    in tee  2
    in f    2   4
    in tee  4
    in f    3   6
    in tee  6
    in f    4   8
    in tee  8
    in f    0   0
    in f    1   2
    in f    2   4
    in f    3   6
    in f    4   8
    
[/code]

上記のとおり、"in f"の行が全部で10行、出力されます。  
期待していたのは、"in f"の行が5行、出力される動作です。

なぜ期待どおりの動作でないのかを教えてください。


CC BY-SA 3.0
2016-12-03T14:36:40.677
30874
2016-12-05T01:59:53.103
19809
question
ocaml
OCamlのExtLibのEnum


`clone`された列挙は元の列挙と独立して要素生成関数が消費時に呼び出されるようですね。ダブって出力されるのはそのためです。

メモリリークを避けるデザインだと思いますが、列挙は遅延リストとは違って`clone`されたからといって片方の要素生成の結果がメモ化されてもう片方に使われるというのではないと思います。生成要素を`clone`間で共有するには`clone`する前に`Enum.force`で明示的に要素を生成する必要があります。


CC BY-SA 3.0
2016-12-05T01:49:30.907
30903
2016-12-05T01:59:53.103
2016-12-05T01:59:53.103
898
898
30874
answer