Java.use(better);

前の記事次の記事
Java.use(better);


Episode#09

クロージャーの代用表現 -- 配列と別れる50の方法


《関連記事》

□ 抽象クラス OCLCollection を具現する

準備が整ったので、抽象クラス OCLCollection を具現した、

class Sequence extends OCLCollection implements Expression {
  private Iterable items;
  public Sequence(Iterable iterable) {
    items = iterable;
  }

クラス Sequence を定義します。このとき、メソッド iterate を実現するだけで、他のメソッド collect/select を利用できます。

  public List iterate(
    Iterate method, List acc) {
    for (int value: items) acc = method.call(acc, value);
    return acc;
  }

for ブロックでは、コレクションの各要素 value を順に参照しながら、第1引数に指定した操作 method を施した結果 method.call(acc,value) を第2引数に指定したコレクション acc に累積して、その結果をリターン値として返します。

□ iterate 操作を利用する

素数を求める例題を使って、iterate 操作の理解を深めます。

  static List prime(int n) {
    final int m = (int)Math.sqrt*1.iterate(new Iterate() {
      public List
      call(List acc, final int n) {
        return new Sequence(acc).select(new Select() {
          public boolean call(int e) {
            return e==n || e%n != 0;
          }});
      }},
      range(2,n));
  }
  ...
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

インターフェース Iterate に準拠する、無名クラスのインスタンスを用意するときに、第1引数には、インターフェース Iterate に準拠する任意のインスタンスを指定して、素数でないもの削除します。また、第2引数には、n 以下の数列を指定します。

インターフェース Select に準拠する、無名クラスのインスタンスを用意するときに、メソッド call の本体では(各要素 e が n と同じでないなら)各要素 e が n の倍数かどうかを判定するだけです。

素数を求めるのに有効な「エラトステネスの篩」とは、指定した整数 n 以下の素数を求めたいときに、最初の素数 2 から始めて昇順に(それと同じ数を除いて)その倍数をすべて取り除くと、最後に素数だけが残るというものです。

      call(List acc, final int n) {
        return new Sequence(acc).select(new Select() {
          public boolean call(int e) {
            return (nと同じ数) || (nの倍数でないもの);
          }});
      }},
      (2からnまでの数列);

ここで注目に値するのは、エラトステネスの篩に固有の部分を除くと、残りのコードの断片は、他の問題解決にも再利用できることです。事実、同じコードの断片はすでに、偶数列を求める例題で紹介しました。

 ↑ TOP

》作業中です《

update*13/02/04 20:09:14

*1:double)n); return new Sequence(range(2,m