Python3000のmap,filterの仕様変更は凄い可能性があるかも

Python3000ではmapとfilterがイテレータブルなオブジェクト(それぞれmap object, filter object)を返す仕様になっている。初めて聞いたときは「うげっ、面倒だな」と思った。けれど、イテレータブルなオブジェクトを返すということは、mapとfilterをよく使うプログラムで、巨大なリストが作られては消える状況がなくなるということだ。
これって工夫の仕方しだいでSchemeの遅延ストリームのように、mapとfilterを使って短くて効率のよいプログラミングのやり方になるんじゃないかと思った。
ここでmapを使った例を。0からある整数までを2倍して1足したリストを得たいとする。この問題をmapを使って解くと下のようになる。Haskellの無限リストに似せて書いてみた。

def integer():
    a = 0
    while True:
        yield a
        a += 1
def take(n, it):
    seq = []
    for _ in range(n):
        try:
            item = next(it)
            seq.append(item)
        except:
            return seq
    return seq
def double(x): return 2*x
def successor(x): return x+1

take(100, map(successor, map(double, integer())))

上のコードはPython3000ならまともに実行できる。まずmapにイテレータが渡されて、関数doubleを適用した値を返すイテレータを返す(正確にはmap object)。その値を左側のmapが受け取り、関数successorを適用した値を返すイテレータを返す。そのイテレータから100個の要素を取り出す。実行結果は以下のようになる。

[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199]


headプログラムもかいてみた。

import sys
def getlines():
    while True: yield input()
take(10, map(print, getlines()))

ちなみに内包表記はPython3000でもリストを返すので上のようなプログラムを書くのはたぶん無理。

こう見てみると、map,filterの仕様の変更は至極まともというかものすごい便利になる可能性があるように思えてきた。