Cyanのletについて
では、letは何なのかというと、関数型言語のようにプログラムを記述するためのマクロです。letマクロによって、letとnamed letの両方が書けます。(正確にはlet*です。)
let^(&opt x = 1, y = 2): say(x + y) let(loop)^(&opt n = 10): if(n == 0): 1 else: n * loop(n - 1)
letマクロは、引数が1つならば通常のletと判断し、渡された関数を呼び出します。引数が2つならばnamed letと判断し、第一引数のシンボルに第二引数の関数を代入してから関数を呼び出します。
関数などどこにあるのかと思われるかもしれませんが、ここではRubyのブロック付きメソッド呼び出しのような構文を利用しています。上に挙げた例の1つ目の式は次のコードと等価です。
let(^(&opt x = 1, y = 2){ say(x + y) })
^(&opt x = 1, y = 2){ say(x + y) }というのが関数です。ここで、&optというのは、Common Lispの&optionalにあたります。
letマクロでは渡された関数を引数なしで呼び出すので、オプショナルな引数が自動的に初期化されてからブロックが実行されるという仕組みです。このブロック付きメソッド呼び出しのような構文については、http://www.geocities.jp/takt0_h/cyan/doc/ref/indent-block.htmlをご覧ください。
ちなみに、実際のletマクロの定義は、以下の通りです。
mac(let)^(obj, &opt func): if(func.null?()): `(?obj)() else: `begin: ?obj := ?func (?obj)()