D2.007でクロージャがやってきたよ

いたるところで話題になってますけどD2.007にしてようやくクロージャきたですよ。ダウンロードはChange Logから。
http://www.digitalmars.com/d/changelog.html
でまあクロージャ使ってBrainfuckインタプリタ書いてみました。前にクラスとか使ってそれっぽく書いたときよりずっとスッキリしました。

クロージャ」とやらに対する俺の認識

「使えるとBrainfuckインタプリタが楽に書けるよね!」

import std.stdio;
import std.string;

alias void delegate() Exp;
Exp[char] exptable;

Exp readblock(FILE* input)
{
  Exp[] block;
  int c;
  while((c=fgetc(input))!=EOF){
    if(c in exptable){
      block ~= exptable[c];
    }
    else if(c=='['){
      block ~= readblock(input);
    }
    else if(c==']'){
      return {while(mem[pt]){foreach(op ; block){op();}}};
    }
  }
  return {foreach(op ; block){op();}};
}

byte mem[30000];
int pt = 0;
int main(string[] args)
{
  exptable['+'] = {++mem[pt];};
  exptable['-'] = {--mem[pt];};
  exptable['>'] = {++pt;};
  exptable['<'] = {--pt;};
  exptable[','] = {mem[pt] = cast(byte)getchar();};
  exptable['.'] = {putchar(mem[pt]);};

  if(args.length!=2){
    writefln("%s input", args[0]);
    return 1;
  }
  FILE* input = fopen(args[1], "r");
  if(input is null){
    writefln("cannot open %s", args[1]);
    return 1;
  }
  Exp main = readblock(input);
  main();

  return 0;
}

ほんでC言語で色々書き方での速度比較してみたときのコードより速いという。

% dmd bfi_closure.d
gcc bfi_closure.o -o bfi_closure -m32 -Xlinker -L/mnt/data/dmd/bin/../lib -lphobos2 -lpthread -lm
% time (repeat 10 ./bfi_closure quine2.b >/dev/null)
0.632 user 0.024 system 0.657 total
% dmd -O bfi_closure.d
gcc bfi_closure.o -o bfi_closure -m32 -Xlinker -L/mnt/data/dmd/bin/../lib -lphobos2 -lpthread -lm
% time (repeat 10 ./bfi_closure quine2.b >/dev/null)
0.476 user 0.024 system 0.502 total

test