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

IronScheme を使ってみた

C# から手軽に Scheme のコードを呼び出したくて。


IronScheme をインストールした後、.NET なプロジェクトに IronScheme.dll と IronScheme.Closures.dll を参照設定に追加すれば一通り使えました。

using System;
using IronScheme;
using IronScheme.Runtime;

static void Main(string[] args) {
    Console.WriteLine("(+ 1 2)".Eval()); // => 3
    Console.ReadKey();
}

あっけなく。


次に Scheme 側の手続きを C# で呼び出してみます。

"(define (add-one-func i) (+ i 1))".Eval();
var addOneFunc = "add-one-func".Eval<Callable>();
Console.WriteLine(addOneFunc.Call(0)); // => 1
Console.WriteLine(addOneFunc.Call(5)); // => 6
Console.WriteLine(addOneFunc.Call(10)); // => 11

あっけなく。


最後に C# 側の関数 (Func) を Scheme で呼び出してみます。

int i = 0;
Func<int> incrementFunc = () => i++;

"(define increment-func {0})".Eval(incrementFunc.ToSchemeProcedure());

が、no expression in body と怒られてしまいます。
IronScheme の Eval() が悪さをしているっぽいのですが (引数で渡したオブジェクトがいったんシンボルになってる)、Scheme レベル 0 なのであんまり深く追っていません。

"(define increment-func '())".Eval();
"(set! increment-func {0})".Eval(incrementFunc.ToSchemeProcedure());
Console.WriteLine("(increment-func)".Eval()); // => 0
Console.WriteLine("(increment-func)".Eval()); // => 1
Console.WriteLine("(increment-func)".Eval()); // => 2
Console.WriteLine("(increment-func)".Eval()); // => 3

とすると、とりあえず動きました。


他にも、

foreach (var val in "'(1 2 3 4 5)".Eval<Cons>()) {
    Console.WriteLine(val);
}

のように、Cons が IEnumerable だったりして面白いです。


IronScheme 自体の初期化が重いのが難点ですが、常駐系のアプリであれば結構使えそうです。