読者です 読者をやめる 読者になる 読者になる

堕(惰)プログラマ開発記録

タイトル変えようかなとも思ってるけれど,思い浮かばない

DartでBindとジョブキューみたいなの作ってみた

Dart

Bindを作成

Dartに関数の引数だけ指定して演算はすぐ行わないという,Boost.Bind的な何かが欲しかったので書いてみました.
C++のテンプレートと違って,Genericsの考え方があまりよく解っていないので間違っているかも知れませんが,無理やり描き切ってみました.

"typedef 戻り値の型 識別子(引数の型リスト);" とすることによって,識別子を関数の型名に出来ます.
また "戻り値の型 変数名(引数の型リスト)" と関数の引数に書くと,変数(?)のように扱えるようです.

class Bind<Return_Type,Arg_Type>{
  //typedefがここで出来ないからDynamic
  final Dynamic _func;
  final Arg_Type _arg;
  Bind(Return_Type this._func(Arg_Type),Arg_Type this._arg);
  
  Return_Type run() => _func(_arg);
}

すると,こんな宣言があった時,

class Containar
{
  final int i,j;
  const Containar(int this.i,int this.j);
}
int a(int i) => i*16;
int b(Containar c) => c.i * c.j;
int c(List<int> l) => l.length;

こう書けます.

main()
{
  var func1 = new Bind(a,4).run;
  var func2 = new Bind(b,new Containar(2,1024)).run;
  var func3 = new Bind(c,[2,4,8,16,32,64,128,256,512,1024]).run;

  print(func3()); // 10   (cの結果)
  print(func2()); // 2048 (bの結果)
  print(func1()); // 64   (aの結果)
}

ジョブキューの作成

ここまでくるとジョブキューを作ってみたくなります.
並列処理を行うならIsolateを使った方がいいのかも知れませんが,特に並列にする必要もなく,一気に処理を行なってしまいたいときは以下のJobクラスを利用すると楽かもしれません.
このクラスではIsolateで値の引渡しに使えない,自作クラスも適用させることができます.

class Job<Return_Type>{
  //ここもtypedefできないんだよねー
  final List _list;
  Job() : _list = [];
  
  void add( Return_Type func() ) => _list.addLast(func);

  List<Return_Type> run_one([final int n = 1])
  {
    final int length = Math.min(n, _list.length);
    List<Return_Type> result = [];
    
    for(int i=0; i < length; ++i)
      result.add( _list[i]() );
    
    _list.removeRange(0, length);
    return result;
  }

  List<Return_Type> run() => run_one(_list.length);
}

このクラスは次のように使います.
先のBindを共に使用すると,更に広範囲で活用できるようになります.

int a() => 33333333;
int b() => a() + 22222222;
int c(List<int> l) => l.length;

main()
{
  Job<int> j = new Job();                                   // intを戻り値の型とするジョブクラスを定義
  j.add(a);                                                 // 詰める
  j.add(b);                                                 // 詰めるっ
  j.add(new Bind(c,[2,4,8,16,32,64,128,256,512,1024]).run); // 詰めるっ!!
  
  List<int> l = j.run();                                    // ここでジョブを一気に消化し,Listに収納します.
  for(final int i in l) print(i);                           // リストのすべての要素を表示
}

結果:
33333333
55555555
10


いや,作る意味有ったのかなって.
なんか,Dart SDKに似たものありそうだけど……<3/18追記>
クロージャのあるDartではC++ likeなbind()は不要 - Islands in the byte stream
だそうです。

確かに……(汗