lispとrubyとpythonとC# イテレータ

偶数だけ抽出して+1した数値を列挙するコード。
RubyPythonとCommonLisp(series)とC#で書いた。

Rubyは遅延評価しないのが微妙。
Ruby1.9イテレータの意図がよく分からない。
ブロックを省略するとEnumeratorが返るけど、なんでそうなってるんだろ。
ブロック書いてあってもEnumeratorのがよくないか?っていうかそっちの動作を期待してしまう。
seriesもPython3.0もLINQも遅延評価するんだし・・・。
何してもEnumeratorが帰って必要に応じてto_aすることにするほがよくないか?ってそれじゃLINQと一緒か。

Pythonは。。。うーーん。なんか一貫性がない気がしてしまう。
itertoolsとfor inで回すコードの同居がしっくりこない。
リスト内容表記も同様。
itertoolsを使うなら関数型っぽくっていうか宣言的に書きたくなるのに、for inを書かないといけなくなると萎える。

CommonLisp(series)
これはこれでいいんじゃないか、と思う。(依怙贔屓か)
まーでもやっぱ前置なんだよな。
メソッドチェインってやっぱ、
xxx.select #いるやつえらんでー
.map #加工してー
  .each #出力ー
と後ろにどんどん書いていくのが気持ちいいんだろうから、何か書いては前に戻って関数を書くのがいまいち。慣れの問題ってのもあるけど。

C#
一番書いてるからだろうけど、いい感じ。
メソッドの名前がSQLに引きずられたせいでヘンに分かりにくいところもあるような気がするけど。

Ruby

[1,2,3,4,5].select{|e|
  puts "select:" + e.to_s
  e % 2 == 0
}.map{|e|
  puts "map:" + e.to_s
  e+1
}.each{|e|
  puts e
}
#->select:1
#  select:2
#  select:3
#  select:4
#  select:5
#  map:2
#  map:4
#  3
#  5
#=>[3, 5]

Python

import itertools

for e in map(lambda e:print("map:" + str(e)) or e + 1, itertools.filterfalse(lambda e:print("filterfalse:" + str(e)) or e % 2 != 0,[1,2,3,4,5])):
    print(e)
#->filterfalse:1
#  filterfalse:2
#  map:2
#  3
#  filterfalse:3
#  filterfalse:4
#  map:4
#  5
#  filterfalse:5

#こっちのがPythonっぽいか?
#リスト内包表記
[e + 1 for e in itertools.filterfalse(lambda e:e % 2 != 0,[1,2,3,4,5])]
#=>[3, 5]

CommonLisp series

(require 'series)

(series::install)

(#M
 (lambda (e) 
   (format t "map-fn:~A~%" e)
   (1+ e))
 (series:choose-if (lambda (e) 
       (format t "choose-if:~A~%" e)
       (= (mod e 2) 0)) #Z(1 2 3 4 5)))
;;->choose-if:1
;;  choose-if:2
;;  map-fn:2
;;  choose-if:3
;;  choose-if:4
;;  map-fn:4
;;  choose-if:5
;;=>#Z(3 5)

C#

using System;
using System.Collections.Generic;
using System.Linq;

class Test
{
 public static int Main(string[] args)
 {
  var lst = new List<int>(new int[]{1,2,3,4,5});
  lst.Where(i => {
       Console.WriteLine("Where:" + i.ToString());
       return i % 2 == 0;
       })
  .Select(i => {
     Console.WriteLine("Select:" + i.ToString());
     return i + 1;})
  .ToList()
  .ForEach(i => Console.WriteLine(i.ToString()));
  return 0;
 }
}
//->Where:1
//  Where:2
//  Select:2
//  Where:3
//  Where:4
//  Select:4
//  Where:5
//  3
//  5