イテレーターという抽象概念にもの思い

元ネタ:

最近、Java のコードばかり書いています。

Java には、Python にはない wikipedia:抽象型 としてのインターフェースがあります。
パーフェクト Java から引用すると、インターフェースは、

オブジェクトにそのインターフェースの決めた振る舞いを期待することの表明

だと説明されています。また Java でプログラミングする上で、インターフェースを意識した抽象化が、複雑さの軽減、保守しやすいコードを書くのに重要だとあります *1

以前、EuroPython 2011 のイベントレポートを執筆した際に *2 、私はイテレーターという用語の扱い方に何となく腑に落ちていませんでした。Python では抽象クラスやインターフェースが言語機能として提供されていません。そのとき @ に「イテレーターはインターフェースだと考えたら良い」と教えてもらって、分かったような分かってないような日々を過ごしていました。

wikipedia の定義によると、

イテレータ (Iterator) とは、プログラミング言語において配列やそれに類似するデータ構造の各要素に対する繰返し処理の抽象化である。

イテレータ - Wikipedia

とあります。イテレーターと聞いて Python で言う iterable なオブジェクトであるリストやタプルをイメージしてしまっていたのが理解を妨げていました。

また Java の話しに戻ります。

最近、Java のコードばかり、、、あっ、違う。

閑話休題Java5 から利用できる拡張 for 文という構文を使うと、Python の for in 文と同じような感覚でイテレーターを扱えます。例えば、インターフェース java.util.List の定義を調べてみます。すると、java.util.Iterator を返すインターフェース java.util.Iterable を継承していることが分かります。UML で書くと、こんな感じです (たぶん) 。

Java の Iterable インターフェースの iterator() メソッドが、Pythonイテレーター型をサポートするための __iter__() メソッドIterator インターフェースの next() メソッドが同じく Python で言う next() メソッドに相当します *3 。つまり、どちらの言語もほとんど同じような仕組みになっているわけです。

java.util.List で宣言したオブジェクトであれば、イテレーターのインターフェースを備えている (と期待できる) ので、どんなデータ型であっても拡張 for 文で繰り返し処理できます。言い換えれば、Java.util.List と宣言することが、繰り返し処理できることの表明であり、プログラマへもその意図を伝えられます。

インターフェースにより、型の違いや実装の詳細を意識させずに抽象化できることが Java におけるパラダイムの1つなんだと少し分かってきました。つまり、あるデータ型のオブジェクトが与えられたとき、

List<Item> data = new myData();

data オブジェクトの詳細を知らなくても iterable なオブジェクトだと分かります。もちろん Python でも似たようなことはできます。

class MyIterable(object):
    def __iter__(self):
        return self
    def next(self):
        return self.next()

class MyData(MyIterable):
    ...

data = MyData();

この場合、継承している MyIterable クラスの実装を覗き見ることで、あぁこれは iterable なオブジェクトなんだと分かるわけですね。

JavaPython で一体何が違うのか。

Javaイテレーターという抽象化された概念とその実装がインターフェースを使うことで明確に分離されています。しかし、Python の場合、分離されるかどうかは実装依存になってしまいます。MyIterable クラスを定義せずに直接、MyData クラスに __iter__() と next() メソッドを実装しても構いません。このことが私にとっては、イテレーターと呼び方を変えても、結局のところはリストやタプルのようなオブジェクトのことなんでしょ、、、といった、抽象概念としてのイテレーターと iterable なオブジェクトとの違いを混同して考えてしまう要因となっていました。

Python でプログラミングするだけなら、混同して考えてもそう害はないのかな?という気もしますが、プログラミング一般の概念として他の人と話したときにちょっと違和感を感じたものの正体がようやく分かってきた気がします。また Java を勉強していたら Python の特徴をより理解した気持ちになってちょっと嬉しかったです。

まとめると、最近、Java のコードばかり書いているんです。

パーフェクトJava (PERFECT SERIES) (PERFECT SERIES 2)

パーフェクトJava (PERFECT SERIES) (PERFECT SERIES 2)