余談ですよ2
http://www.jmuk.org/d/?path=2006/01/08#d08t02
[id:soutaro:20060108]
sequenceがあっても、mapがなければループを自前で書く必要があるわけで、じゃあ、ループをfor文なしにどう書くの?といったら、再帰構文で書けるから要らないよ、ってことでしょ、という話だと考えていたのだけれど・・・
そもそも、末尾再帰の最適化をしない言語の場合は、再帰構文でループを書くことができない。だから、そういう言語(CやJavaやPascalや・・・)では、while文やfor文は、言語にとって不可欠の存在だということ。それに対し、末尾再帰の最適化をする言語(LispやMLやHaskellや・・・)では、while文やfor文は、単なる構文糖衣に過ぎない。
-
-
- -
-
でも、なぜ(while文ではなくて)「for文」がないのか?ということなら、sequenceがあるからとかmapがあるからとかという理由であたっていると思う。for文というのは、シーケンスや配列操作を楽にするための、while文に対する構文糖衣だとも言えるからだ。
Delphi : クロージャ
[id:lethevert:20060107:p1]で作成したクロージャを使って、memoizeとfixの問題「[id:lethevert:20050904:p3]」を書こうと思っているのだけれど・・・
maker関数が上手く作れない。というのは、IClosureとPointerを交換できないのだ。(前回、TObjectとして定義したIClosureは、Pointerを使って書き直している)
クロージャオブジェクトを複数のパターン作成するのはなるべく避けたいのだけれど・・・
-
-
- -
-
と思ったのだが、自己解決した。
recordでインターフェースを包んでしまえばよい。
-
-
- -
-
と思ったのだが、やはり上手くいかない・・・。
-
-
- -
-
でけた!!
一部、レコードの解放ができていないところがあるけど、一応動く。
program fib_fix; {$APPTYPE CONSOLE} uses SysUtils, OptClosure in 'OptClosure.pas'; //キャストのエイリアス type _i = Integer; _p = Pointer; //IClosureのラッパー type PClosure = ^TClosure; TClosure = record _: IClosure; end; function Init(c: IClosure): PClosure; begin New(Result); Result._ := c; end; procedure Final(e: PClosure); begin Dispose(e); end; //固定点を求める関数 function fix(maker: IClosure): IClosure; function f(obj: Pointer; maker: PClosure): Pointer; var ff: TClosure; //受け渡しのみ begin ff._ := _(@f, Init(maker._), @Final); Result := PClosure(maker._._(@ff))._._(obj); end; begin Result := _(@f, Init(maker), @Final); end; //フィボナッチ関数を作る関数 function fib_maker(ff: PClosure): PClosure; function f(I: Integer; ff: PClosure): Integer; begin if I = 0 then Result := 0 else if I = 1 then Result := 1 else Result := _i(ff._._(_p(I-1))) + _i(ff._._(_p(I-2))); end; begin New(Result); //TODO: この解放が行えていない。 Result._ := _(@f, Init(ff._), @Final); end; var fib: IClosure; I: Integer; begin //フィボナッチ関数の作成 fib := fix(_(@fib_maker)); //テスト実行 for I := 0 to 10 do begin Writeln(IntToStr(I) + ' -> ' + IntToStr(_i(fib._(_p(I))))); end; end.
ちなみに、ここでつかっったOptClosure.pasは、以下です。
続きを読む