yield と collect イディオム

小町算、parse とか eval とかしないで解こうと思ったら、kinaba さんに elegant な解答をかかれたので萎えてやめた。

そういえば、yield って今まで存在すら知らなかったんですが、ここみてわかった。ずいぶん前に id:mmatsuoka さんのところで知った、collect イディオムの遅延バージョンですね!

let collect f =
  let acc = ref [] in
  let keep x =
    acc := x::!acc in
  f keep;
  List.rev !acc

collect では List の実体を作るが、yield では代わりに iterator を作るという寸法のようだ。こんなのできたのか、知らなかった。Pythoniterator の文化は本当に見事だと思っていて、非常に統一されている。Python が好きな理由の一つはこの辺り。

yield では iterator を作りますが、代わりに1引数関数を適用させると捉えるのもおもしろい。List とは 関数 f を次々に適用させる関数のことだったんだよ!

let range n f =
  for i = 0 to n-1 do f i done
;;

let lst = range 10 in
lst print_int;;
0123456789

let map f lst g =
  lst (fun x -> g (f x))
;;

let lst2 = map (( * ) 2) lst in
lst2 print_int;;
024681012141618

いや、まぁホントにどうでもいいんだけど。