barutanGNE's blog

kindleで読んだ本の感想や、プログラミングに関する記事など。

PythonのmapはHaskellのzipWith?

Pythonでmapを使う

>>> f1 = lambda x: x * 2
>>> ls1 = map(f1, range(10))
>>> list(ls1)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>> f2 = lambda x, y: x*2 + y*2
>>> ls2 = map(f2, range(10), range(10))
>>> list(ls2)
[0, 4, 8, 12, 16, 20, 24, 28, 32, 36]
>>> f3 = lambda x, y, z: x*2 + y*2 + z*2
>>> ls3 = map(f3, range(10), range(10), range(10))
>>> list(ls3)
[0, 6, 12, 18, 24, 30, 36, 42, 48, 54]

Python3.3では、mapはイテレータを返すので、結果の全体を見たいときはlistをかけてやる必要がある。

1引数の関数でmapするときには、Haskellと変わらない。しかし、Pythonのmapは可変引数で、2引数の関数をmapしたり、3引数の関数をmapしたりできる。これらは、HaskellではzipWithやzipWith3になる。

同じことをHaskellでやる

Prelude> let f1 = \x -> x*2
Prelude> map f1 [0..9]
[0,2,4,6,8,10,12,14,16,18]
Prelude> let f2 = \x y -> x*2 + y*2
Prelude> zipWith f2 [0..9] [0..9]
[0,4,8,12,16,20,24,28,32,36]
Prelude> let f3 = \x y z-> x*2 + y*2 + z*2
Prelude> zipWith3 f3 [0..9] [0..9] [0..9]
[0,6,12,18,24,30,36,42,48,54]

インタプリタでの実行をそのまま貼り付けているので、letとかPreludeが邪魔なのはごめんなさい。

言われてみると、zipWithをzipWith2と思ってみると、mapってzipWith1と思える関数だな。

他の言語でのmapやzipWithはMap(Wikipedia))に載っている。