Processingで無名関数的なことしてみた

### はじめに

自分は大学でProcessingを勉強し始め、その後Rust言語を使うようになりました。まあProcessingは狭い世界で、やれることが全然少ない！Rust最高！となったわけですが、Processingも長いこと使っていて愛着があるので、なにかProcessingにはない機能を再現してみたいと思いました。その一つが無名関数です。

## 無名関数が欲しくなったワケ

事の発端は、Processingで素数を求めるプログラムを作成していた時です。すぐに完成したのですが、Rustならもっと短くかけるのでは？と思い実装してみました。以下がこれらのコードです。

```java
// Processing

ArrayList<Integer> exception_list = new ArrayList();
loop: for(int n=2; n<100; n++){
  for(int m: exception_list){
    if(n % m == 0){ continue loop; }
  }
  println(n);
  exception_list.add(n);
}
```

```rust
// Rust

let mut exception_list = vec![];
'Loop: for n in 2..100 {
    if exception_list.iter().any(|m|n % m == 0) { continue 'Loop; }
    println!("{}", n);
    exception_list.push(n);
}
```

アルゴリズムが簡単なのでそこまでの変化ではありませんでしたが、Rustの場合、簡単に説明すると「配列の全要素に対して、それを引数にとってbool値を返す関数を適用させ、その中の一回でもtrueが返った場合に」trueを返す`any()`というメソッドがあります。
Processingでは無名関数(クロージャやラムダ式とも言います)が使えないのですが、これと同じことはできないかと考えていました。

## インスタンス化と同時に関数を定義

Processingでは`new ClassName(...)`によりインスタンスを作りますが、その際に関数のオーバーライド(abstractクラスに関しては定義)ができます。書いている途中で思い出しましたが、リスナーを登録するときにも使われていますね。

```java
abstract class MyClass {
  abstract void func();
}

void setup() {
  MyClass c = new MyClass(){
    public void func(){ // publicでなければエラー
      println("Hello, world!");
    }
  };
}
```

そこで以下のようにして、**機能だけは**無名関数のようなものを実装してみました。

```java
abstract class fn<R, A> {
  abstract R func(A arg);
}

class Vec<T> {
  ArrayList<T> list = new ArrayList();
  
  void add(T item) {
    this.list.add(item);
  }
  
  boolean any(fn f) {
    for(T item: this.list){
      if( (boolean)f.func(item) ){ return true; }
    }
    return false;
  }
}

void setup() {
  Vec<Integer> vec = new Vec();
  for(int n=2; n<100; n++){
    final int _n = n;
    if(vec.any(new fn<Boolean, Integer>(){
      public Boolean func(Integer m){ return _n % m == 0; }
    })){
      continue;
    }
    
    println(n);
    vec.add(n);
  }
}
```

...前より長いです。しかも書きづらいです。だから**機能だけは**無名関数なんです。
では解説していきます。

```java
abstract class fn<R, A> {
  abstract R func(A arg);
}
```

まずは無名関数というものを定義していきます（定義した時点で無名じゃないというツッコミはNGです）。
`abstract`キーワードにより、このクラスは関数を定義させなければ使えなくなりました。必須のコードではありませんが、このクラスの`func`関数はデフォルト実装をもたせたくないので悪くはないかなと。
`<R, A>`の部分なのですが、これはジェネリクスというもので、動的に型を決定できます。「なにかしらの型ではあるが、今はまだわからない。とりあえず名前だけは作っておくから使えるよ。」といった意味でとらえていただければ問題ありません。

```java
class Vec<T> {
  ArrayList<T> list = new ArrayList();
  
  void add(T item) {
    this.list.add(item);
  }
  
  boolean any(fn<Boolean, T> f) {
    for(T item: this.list){
      if( f.func(item) ){ return true; }
    }
    return false;
  }
}
```

Processingの`ArrayList`はもちろんですがRustで使われているような`any`メソッドを持っていません。ので、ラッパークラス的なものを作成していきます。ここでもジェネリクスが用いられており、`ArrayList`同様どんな型に対してもインスタンスを作成できます。これは`any`メソッドを持った`ArrayList`と考えてください。
ここて定義されている`any`メソッドは、型パラメータが`Boolean`と`T`(この`Vec`クラスで用いている`T`と同じ型)である`fn`クラスのオブジェクトを引数にとり、`f`という名前で引数変数を作っています。拡張for文(foreachみたいなもの)によって渡されたリストの中身を引数として、`func`関数を呼び出しています。ただ、`func`関数はまだ定義していませんでしたね？これは、引数として与える際に実装しています。次をご覧ください。

```java
void setup(){
  Vec<Integer> vec = new Vec();
  for(int n=2; n<100; n++){
    final int _n = n;
    if(vec.any(new fn<Boolean, Integer>(){
      public Boolean func(Integer m){ return _n % m == 0; }
    })){
      continue;
    }
    println(n);
    vec.add(n);
  }
}
```

`Integer`型の可変長配列が欲しいので、`Vec<Integer>`という型のインスタンスを作ります。
変数`vec`に対してこの部分5行目で`any`メソッドを使っており、引数には`fn`クラスのインスタンスを渡しています。ここで`func`関数を定義を行なっています。
`Vec<Integer>`型のオブジェクト`vec`に実装されている`any`メソッドの引数は、`T`が`Integer`に決定したので`fn<Boolean, Integer>`となります。したがって、ここで作られる`fn`クラスの型パラメータも合わせて設定しないといけません。同時に、実装する`func`関数の引数と返り値の型も正しく揃えます。
定義した`func`関数は単純で、`_n`という整数を与えられた整数で割り切れるか否かを返しているだけです。この`_n`なのですが、単純に`n`を渡そうとするとエラーになってしまいます。しょうがなくエラー回避のために`final`宣言をした変数`_n`を使用しています。

あとは同じですね。結果的にそれまで求めた素数で割り切れなかった場合に、出力してからリストに加えています（このアルゴリズムをエラトステネスの篩といいます）。

## まとめ

外で定義されている変数を使うのに一手間必要だったり（そもそも`final`宣言することでできなくなることもあるのでは...）、無名関数と言いつつ無名じゃなかったりと、実用的かと言われれば微妙ではありますが、このようにして関数を渡すこともできるという記事でした。