<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2japanesefull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">

<channel>
	<title>MASDA</title>
	
	<link>http://www.metaphor.co.jp/masuda/blog</link>
	<description />
	<pubDate>Sat, 14 Feb 2009 00:14:49 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>ja</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/masda" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="masda" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>PerspectiveProjection</title>
		<link>http://www.metaphor.co.jp/masuda/blog/?p=33</link>
		<comments>http://www.metaphor.co.jp/masuda/blog/?p=33#comments</comments>
		<pubDate>Tue, 03 Feb 2009 01:15:24 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.metaphor.co.jp/masuda/blog/?p=33</guid>
		<description><![CDATA[自分が担当してるSWFがルート(stage直下のドキュメントクラス)として起動されるケースと、子として読まれるケースがある案件で、パースの見た目が異なってハマった。。PerspectiveProjectionがnullじゃないDisplayObjectがネストされたとき、どういう扱いになるんだろう？？
3D使うのはそこだけだったので、addChildされたとき上方のperspectiveProjectionを全てnullにしつつ、ルートの表示オブジェクトのみ値を設定して結果を合わせた。けどなんか気持ち悪い。。

var o:DisplayObject = this;
while (o.parent != stage) {
  o.transform.perspectiveProjection = null;
  o = o.parent;
}

リキッドの場合は、プロジェクションセンターも更新しないと意図通りにならないかも・・。

private function onResize(evt:Event):void {
  var proj:PerspectiveProjection = root.transform.perspectiveProjection;
  var pt:Point = proj.projectionCenter;
  pt.x = stage.stageWidth * 0.5;
  pt.y = stage.stageHeight * 0.5;
  proj.projectionCenter = pt;
  root.transform.perspectiveProjection = proj;
}

]]></description>
			<content:encoded><![CDATA[<p>自分が担当してるSWFがルート(stage直下のドキュメントクラス)として起動されるケースと、子として読まれるケースがある案件で、パースの見た目が異なってハマった。。PerspectiveProjectionがnullじゃないDisplayObjectがネストされたとき、どういう扱いになるんだろう？？</p>
<p>3D使うのはそこだけだったので、addChildされたとき上方のperspectiveProjectionを全てnullにしつつ、ルートの表示オブジェクトのみ値を設定して結果を合わせた。けどなんか気持ち悪い。。</p>
<pre class="prettyprint">
var o:DisplayObject = this;
while (o.parent != stage) {
  o.transform.perspectiveProjection = null;
  o = o.parent;
}
</pre>
<p>リキッドの場合は、プロジェクションセンターも更新しないと意図通りにならないかも・・。</p>
<pre class="prettyprint">
private function onResize(evt:Event):void {
  var proj:PerspectiveProjection = root.transform.perspectiveProjection;
  var pt:Point = proj.projectionCenter;
  pt.x = stage.stageWidth * 0.5;
  pt.y = stage.stageHeight * 0.5;
  proj.projectionCenter = pt;
  root.transform.perspectiveProjection = proj;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.metaphor.co.jp/masuda/blog/?feed=rss2&amp;p=33</wfw:commentRss>
		</item>
		<item>
		<title>GC判定再び</title>
		<link>http://www.metaphor.co.jp/masuda/blog/?p=30</link>
		<comments>http://www.metaphor.co.jp/masuda/blog/?p=30#comments</comments>
		<pubDate>Fri, 19 Dec 2008 15:24:44 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.metaphor.co.jp/masuda/blog/?p=30</guid>
		<description><![CDATA[GCされたかテストするクラスの改良版。
最後の参照を消すとき、

_instanceVar = null; //これでいつか解放されるはずだが・・

と書いているところを、

//常に戻り値のnullが代入されるが、同時に漏れを確認
_instanceVar = GC.shouldBeGarbage(_instanceVar); // 以降、ゴミとして回収されるべき！

と書くことにします[*注]。これで参照の消し忘れがあれば、直後にエラーになってくれます。多分。
ちなみにFlexでは子SWFがアンロードされると、以下のように表示されるのでこれの出番は少ないかもしれません。

[SWF のアンロード]Users:masuda:Documents:Flex Builder 3:Test:bin-debug:child.swf

以下にいくつかサンプルを挙げます。
ドキュメントクラスのコンストラクタに書かれているコードだと思って下さい。
ローカル変数はGCされる:

var o:DisplayObject = new Sprite();
GC.shouldBeGarbage(o); //=> GC succeeded: 4489216 => 4771840

インスタンス変数に退避したため延命され、GCされない:

var o:DisplayObject = new Sprite();
_instanceVar = o;
GC.shouldBeGarbage(o); //=> Error

表示リストに残っているため、GCされない:

_instanceVar = new Sprite();
addChild(_instanceVar);
//removeChild(_instanceVar); //この行が必要だった
_instanceVar = GC.shouldBeGarbage(_instanceVar); //=> Error

ローカル変数はクロージャに延命され、クロージャはstageに延命されるのでGCされない:

var o:DisplayObject = new Sprite();
addChild(o);
removeChild(o);
GC.shouldBeGarbage(o); //=> Error
//o = null; //この行が必要だった
stage.addEventListener(
  Event.ENTER_FRAME,
  function(evt:Event):void {/*どの変数も参照してなくても害*/}
);

クロージャとメモリリークについての親切な解説はこちら:
http://www.imajuk.com/blog/archives/2008/04/post_3.html
以下、ソースコードです:

package {
  import flash.display.Sprite;
 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.metaphor.co.jp/masuda/blog/?p=5">GCされたかテストするクラス</a>の改良版。</p>
<p>最後の参照を消すとき、</p>
<pre class="prettyprint">
_instanceVar = null; //これでいつか解放されるはずだが・・
</pre>
<p>と書いているところを、</p>
<pre class="prettyprint">
//常に戻り値のnullが代入されるが、同時に漏れを確認
_instanceVar = GC.shouldBeGarbage(_instanceVar); // 以降、ゴミとして回収されるべき！
</pre>
<p>と書くことにします[*注]。これで参照の消し忘れがあれば、直後にエラーになってくれます。多分。</p>
<p>ちなみにFlexでは子SWFがアンロードされると、以下のように表示されるのでこれの出番は少ないかもしれません。</p>
<pre>
[SWF のアンロード]Users:masuda:Documents:Flex Builder 3:Test:bin-debug:child.swf
</pre>
<p>以下にいくつかサンプルを挙げます。<br />
ドキュメントクラスのコンストラクタに書かれているコードだと思って下さい。</p>
<p>ローカル変数はGCされる:</p>
<pre class="prettyprint">
var o:DisplayObject = new Sprite();
GC.shouldBeGarbage(o); //=> GC succeeded: 4489216 => 4771840
</pre>
<p>インスタンス変数に退避したため延命され、GCされない:</p>
<pre class="prettyprint">
var o:DisplayObject = new Sprite();
_instanceVar = o;
GC.shouldBeGarbage(o); //=> Error
</pre>
<p>表示リストに残っているため、GCされない:</p>
<pre class="prettyprint">
_instanceVar = new Sprite();
addChild(_instanceVar);
//removeChild(_instanceVar); //この行が必要だった
_instanceVar = GC.shouldBeGarbage(_instanceVar); //=> Error
</pre>
<p>ローカル変数はクロージャに延命され、クロージャはstageに延命されるのでGCされない:</p>
<pre class="prettyprint">
var o:DisplayObject = new Sprite();
addChild(o);
removeChild(o);
GC.shouldBeGarbage(o); //=> Error
//o = null; //この行が必要だった
stage.addEventListener(
  Event.ENTER_FRAME,
  function(evt:Event):void {/*どの変数も参照してなくても害*/}
);
</pre>
<p>クロージャとメモリリークについての親切な解説はこちら:<br />
<a href="http://www.imajuk.com/blog/archives/2008/04/post_3.html">http://www.imajuk.com/blog/archives/2008/04/post_3.html</a></p>
<p>以下、ソースコードです:</p>
<pre class="prettyprint">
package {
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.net.LocalConnection;
  import flash.system.System;
  import flash.utils.Dictionary;

  public class GC {
    private static var sprite:Sprite = new Sprite();

    public static function start():void {
      try {
        new LocalConnection().connect('foo');
        new LocalConnection().connect('foo');
      } catch (e:*) {}
    }

    public static function shouldBeGarbage(value:Object):* {
      try {
        //テストは1フレ後だが、この時点のスタックトレースがほしい
        throw new Error('Probably, it is not garbage:' + value);
      } catch (e:Error) {
        var dict:Dictionary = new Dictionary(true);
        dict[value] = true;
        value = null;

        var before:uint = System.totalMemory;
        GC.start();

        var err:Error = e;
        sprite.addEventListener(Event.ENTER_FRAME, function(evt:Event):void {
          evt.target.removeEventListener(evt.type, arguments.callee);
          for (var key:Object in dict) throw err;
          trace('GC succeeded:', before, '=>', System.totalMemory);
        });
      }
      return null;
    }
  }
}
</pre>
<p>[*注] 以下の例は、全ての参照を消すのに先だってshouldBeGarbageを行うためGCが成功しそうにありませんが、実際のところ、このように書いてもテストをパスします。</p>
<pre class="prettyprint">
GC.shouldBeGarbage(_instanceVar);
_instanceVar = null;
</pre>
<p>恐らく、LocalConnectionによる強制GCの発動は即座に行われずに、一度Flash Playerに制御を戻した後行われているのだと想像しています・・。そうなると、shouldBeGarbage(x)の意味合いとしては、「現在実行中のコードを抜けた後には、xはゴミとなり回収されるべきだ」といったところでしょうか。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metaphor.co.jp/masuda/blog/?feed=rss2&amp;p=30</wfw:commentRss>
		</item>
		<item>
		<title>las3r (2)</title>
		<link>http://www.metaphor.co.jp/masuda/blog/?p=29</link>
		<comments>http://www.metaphor.co.jp/masuda/blog/?p=29#comments</comments>
		<pubDate>Fri, 05 Dec 2008 05:39:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.metaphor.co.jp/masuda/blog/?p=29</guid>
		<description><![CDATA[las3r、Clojure(むしろLisp)がよく分からないまま手探りで弄っています。便利だと思ったのが、アリティによる多重定義と、暗黙のdestructuring-bind(アンパック代入みたいなもん？)。
以下は0〜2個の引数を取るMath.random:

(defn rand
  ([] ((. Math random)))
  ([n] (* n (rand)))
  ([a b]
    (if (< a b)
      (+ a (rand (- b a)))
      (+ b (rand (- a b))))))

(rand -1 1) ;=> -0.689156367443502

要は引数のパターンに応じた振り分けと同時に変数束縛されるようですが、これが再帰関数の場合には特に便利で、例えばリストをペアに区切ったリストにして返す手続きは:

(defn pairs [l]
  (apply
    [...]]]></description>
			<content:encoded><![CDATA[<p>las3r、Clojure(むしろLisp)がよく分からないまま手探りで弄っています。便利だと思ったのが、アリティによる多重定義と、暗黙のdestructuring-bind(アンパック代入みたいなもん？)。</p>
<p>以下は0〜2個の引数を取るMath.random:</p>
<pre>
(defn rand
  ([] ((. Math random)))
  ([n] (* n (rand)))
  ([a b]
    (if (< a b)
      (+ a (rand (- b a)))
      (+ b (rand (- a b))))))

(rand -1 1) ;=> -0.689156367443502
</pre>
<p>要は引数のパターンに応じた振り分けと同時に変数束縛されるようですが、これが再帰関数の場合には特に便利で、例えばリストをペアに区切ったリストにして返す手続きは:</p>
<pre>
(defn pairs [l]
  (apply
    (fn
      ([x] (list (list x)))
      ([x y] (list (list x y)))
      ([x y &#038; z] (cons (list x y) (pairs z))))
  l))

(pairs '(1 2 3 4 5)) ;=> ((1 2) (3 4) (5))
</pre>
<p>ところで、las3rでは{:x 200 :y 400 :time 0.5}と書くと内部的にはMapというオブジェクトになってしまうようなので、Tweener.addTweenの第二引数に渡せません。MapからObjectへ変換するそれらしき関数も見つからなかったので、試しにObjectリテラルに近い書き方ができるマクロを書いてみると:</p>
<pre>
(defmacro obj [&#038; elts]
  (let [o (gensym)]
    `(let [~o (new Object)]
      ;;fnやletのパラメータはdestructuring-bindされる雰囲気。
      ~@(map (fn [[var exp]] `(set! (. ~o ~var) ~exp)) (pairs elts))
    ~o)))

(macroexpand-1 '(obj x 200 y 400 time 0.5))
;=>
;(las3r/let [G__1378 (new Object)]
;  (set! (. G__1378 x) 200)
;  (set! (. G__1378 y) 400)
;  (set! (. G__1378 time) 0.5)
;  G__1378)

(obj x 200 y 400 time 0.5) ;=> [object Object]
</pre>
<p>これで以下のようにだらだらと書かなくて済みます。</p>
<pre>
(. Tweener
  (addTween
    movie-clip
    (let o (new Object)
      (set! (. o x) 200)
      (set! (. o y) 400)
      (set! (. o time) 0.5)
      o)))
</pre>
<p>クリックすると画面上をランダムに移動する四角形はこんな雰囲気:</p>
<pre>
(import '(flash.display Sprite Graphics)
        '(caurina.transitions Tweener))

(def s ((. *stage* addChild) (new Sprite)))

(doto (. s graphics)
  (beginFill 0x0000ff 1)
  (drawRect 0 0 100 100)
  (endFill))

(. s
  (addEventListener "click"
    (fn []
      (. Tweener (addTween
        s
        (obj x (rand (. *stage* width))
             y (rand (. *stage* height))
             time 0.5))))))
</pre>
<p>最後に衝撃のfib(25)の時間比較:</p>
<ul>
<li>ABC<br />
=&gt; 88 msec</li>
<li>AS3<br />
=&gt; 125 msec</li>
<li>las3r<br />
=&gt; 5465 msec</li>
<li>SICP4.1.7をASに移植したもの(比較用)<br />
=&gt; 11255 msec</li>
</ul>
<p>なるほど・・・。<br />
まだきっと伸びしろはありますよね！<br />
速くなるといいなぁ。。</p>
<p>なお、計測の対象は以下の関数:</p>
<p>AS3:</p>
<pre class="prettyprint">
private function fib(n:uint):uint {
  return (n < 2) ? n : fib(n - 1) + fib(n - 2);
}
</pre>
<p>ABC(hxasmを使用):</p>
<pre class="prettyprint">
var ctx:Context = new Context();
ctx.beginClass("Main");
var tint:Index = ctx.type("int");
var m:* = ctx.beginMethod("fib", [tint], tint);
m.maxStack = 3;
ctx.ops([
  OpCode.OReg(1),
  OpCode.OSmallInt(1),
]);
var j:Function = ctx.jump(JumpStyle.JGt);
ctx.ops([
  OpCode.OReg(1),
  OpCode.ORet,
]);
j();
ctx.ops([
  OpCode.ODecrIReg(1),
  OpCode.OThis,
  OpCode.OReg(1),
  OpCode.OCallProperty(ctx.property("fib"),1),
  OpCode.ODecrIReg(1),
  OpCode.OThis,
  OpCode.OReg(1),
  OpCode.OCallProperty(ctx.property("fib"),1),
  OpCode.OOp(Operation.OpAdd),
  OpCode.ORet,
]);
ctx.finalize();

var o:Output = new Output();
Writer.write(o, ctx);
var swf:ByteArray = o.getBytes();

var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(evt:Event):void {
  var klass:Class = ApplicationDomain.currentDomain.getDefinition('Main') as Class;
  callback(new klass().fib); //この引数がコンパイル済みfib
});
loader.loadBytes(swf, new LoaderContext(false, ApplicationDomain.currentDomain));
</pre>
<p>las3r:</p>
<pre class="prettyprint">
var rt:RT = new RT(stage, new OutputStream(trace), new OutputStream(trace));
rt.loadStdLib();
rt.evalStr(
  '(defn fib [n] (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))) fib',
  callback //fnを評価するとコンパイル済みfibがcallbackに渡る
);
</pre>
<p>SICP4.1.7をASに移植したもの:</p>
<pre class="prettyprint">
var fib:Function =
  eval("(define (fib n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))) fib");

/*evalの定義は長いので略*/
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.metaphor.co.jp/masuda/blog/?feed=rss2&amp;p=29</wfw:commentRss>
		</item>
		<item>
		<title>las3r</title>
		<link>http://www.metaphor.co.jp/masuda/blog/?p=28</link>
		<comments>http://www.metaphor.co.jp/masuda/blog/?p=28#comments</comments>
		<pubDate>Mon, 01 Dec 2008 22:30:52 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.metaphor.co.jp/masuda/blog/?p=28</guid>
		<description><![CDATA[clojureというJVM向けLisp方言があるらしいのですが、それのAVM2向けコンパイラがAS3で書かれています。
http://github.com/aemoncannon/las3r/wikis
構文的な違いが結構あり戸惑ったのですが、こちらを見ればだいたいつかめると思います。
Schemeじゃないから当然かもしれませんし、ABC的に実装に難があるからかも分かりませんが、残念ながら:

末尾最適化なし (末尾再帰にはrecurを使えばスタックを消費しない)
継続なし

しかし、それを差し引いてもASにない以下の特徴を楽しむことができます:

マクロが使える
動的コンパイル

しかも、Emacs向けにlas3r-modeが用意されていて、起動中のSWFに対し修正を動的に反映できます。
以下手順:

etc/las3r-mode.elをEmacsのロードパスへ配置
もしなければ、以下もDLしてロードパスへ配置
http-get.el, http-cookies.el, http-post.el
.emacsに以下を追記
(autoload 'las3r-mode "las3r-mode" "Major mode for las3r." t)
(add-to-list 'auto-mode-alist '("\\.lsr$" . las3r-mode))
src/lsr/boot.lsrの最終行、;;(connect-to-eval-pipe)をコメントインしておく
etc/eval_pipe.rbを起動しておく
対象のSWFを起動しておく
Emacsにて*.lsrの編集中にF5 (すると、バッファ全体がevalされる)

この手の試みがじわりじわりと増えてきているような気がしますね・・。
今後が楽しみです。
関連メモ:
http://hg.mozilla.org/tamarin-central/file/d92e466aed84/esc/src/
元?
http://eval.hurlant.com/
上記のAS3版だと思う。las3rはこれの一部を使っている。
http://ariyan-harhid.cocolog-nifty.com/blog/2008/10/tamarin-esc-c-2.html
上記の改良版。実行時エラー情報を詳しく教えてくれたりetc
http://happyabc.org/
OCaml製のSchemeコンパイラ
http://www.bitbucket.org/SumiTomohiko/actionpython/overview/
これは・・？
http://haxe.org/com/libs/hxasm
haXeのABCアセンブラ
http://www.sephiroth.it/weblog/archives/2008/07/expressions_evaluation_at_almost_nati.php
上記のAS3版を基礎としたシンプルな電卓デモ
http://www.anotherbigidea.com/javaswf/avm2/AVM2Instructions.html
見やすい
http://code.google.com/p/as3c/
インラインアセンブラ
]]></description>
			<content:encoded><![CDATA[<p><a href="http://clojure.org/">clojure</a>というJVM向けLisp方言があるらしいのですが、それのAVM2向けコンパイラがAS3で書かれています。<br />
<a href="http://github.com/aemoncannon/las3r/wikis">http://github.com/aemoncannon/las3r/wikis</a></p>
<p>構文的な違いが結構あり戸惑ったのですが、<a href="http://sites.google.com/site/shidoinfo/Home/programing-lang/関数型プログラミング言語/lisp/様々なlisp方言/clojure">こちら</a>を見ればだいたいつかめると思います。</p>
<p>Schemeじゃないから当然かもしれませんし、ABC的に実装に難があるからかも分かりませんが、残念ながら:</p>
<ul>
<li>末尾最適化なし (末尾再帰にはrecurを使えばスタックを消費しない)</li>
<li>継続なし</li>
</ul>
<p>しかし、それを差し引いてもASにない以下の特徴を楽しむことができます:</p>
<ul>
<li>マクロが使える</li>
<li>動的コンパイル</li>
</ul>
<p>しかも、Emacs向けにlas3r-modeが用意されていて、起動中のSWFに対し修正を動的に反映できます。<br />
以下手順:</p>
<ol>
<li>etc/las3r-mode.elをEmacsのロードパスへ配置</li>
<li>もしなければ、以下もDLしてロードパスへ配置<br />
<a href="http://cvs.savannah.gnu.org/viewvc/*checkout*/http-emacs/http-emacs/http-get.el">http-get.el</a>, <a href="http://cvs.savannah.gnu.org/viewvc/*checkout*/http-emacs/http-emacs/http-cookies.el">http-cookies.el</a>, <a href="http://cvs.savannah.gnu.org/viewvc/*checkout*/http-emacs/http-emacs/http-post.el">http-post.el</a></li>
<li>.emacsに以下を追記<br />
(autoload 'las3r-mode "las3r-mode" "Major mode for las3r." t)<br />
(add-to-list 'auto-mode-alist '("\\.lsr$" . las3r-mode))</li>
<li>src/lsr/boot.lsrの最終行、;;(connect-to-eval-pipe)をコメントインしておく</li>
<li>etc/eval_pipe.rbを起動しておく</li>
<li>対象のSWFを起動しておく</li>
<li>Emacsにて*.lsrの編集中にF5 (すると、バッファ全体がevalされる)</li>
</ol>
<p>この手の試みがじわりじわりと増えてきているような気がしますね・・。<br />
今後が楽しみです。</p>
<p>関連メモ:<br />
<a href="http://hg.mozilla.org/tamarin-central/file/d92e466aed84/esc/src/">http://hg.mozilla.org/tamarin-central/file/d92e466aed84/esc/src/</a><br />
元?</p>
<p><a href="http://eval.hurlant.com/">http://eval.hurlant.com/</a><br />
上記のAS3版だと思う。las3rはこれの一部を使っている。</p>
<p><a href="http://ariyan-harhid.cocolog-nifty.com/blog/2008/10/tamarin-esc-c-2.html">http://ariyan-harhid.cocolog-nifty.com/blog/2008/10/tamarin-esc-c-2.html</a><br />
上記の改良版。実行時エラー情報を詳しく教えてくれたりetc</p>
<p><a href="http://happyabc.org/">http://happyabc.org/</a><br />
OCaml製のSchemeコンパイラ</p>
<p><a href="http://www.bitbucket.org/SumiTomohiko/actionpython/overview/">http://www.bitbucket.org/SumiTomohiko/actionpython/overview/</a><br />
これは・・？</p>
<p><a href="http://haxe.org/com/libs/hxasm">http://haxe.org/com/libs/hxasm</a><br />
haXeのABCアセンブラ</p>
<p><a href="http://www.sephiroth.it/weblog/archives/2008/07/expressions_evaluation_at_almost_nati.php">http://www.sephiroth.it/weblog/archives/2008/07/expressions_evaluation_at_almost_nati.php</a><br />
上記のAS3版を基礎としたシンプルな電卓デモ</p>
<p><a href="http://www.anotherbigidea.com/javaswf/avm2/AVM2Instructions.html">http://www.anotherbigidea.com/javaswf/avm2/AVM2Instructions.html</a><br />
見やすい</p>
<p><a href="http://code.google.com/p/as3c/">http://code.google.com/p/as3c/</a><br />
インラインアセンブラ</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metaphor.co.jp/masuda/blog/?feed=rss2&amp;p=28</wfw:commentRss>
		</item>
		<item>
		<title>llfuture</title>
		<link>http://www.metaphor.co.jp/masuda/blog/?p=26</link>
		<comments>http://www.metaphor.co.jp/masuda/blog/?p=26#comments</comments>
		<pubDate>Mon, 01 Sep 2008 10:49:17 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[others]]></category>

		<guid isPermaLink="false">http://www.metaphor.co.jp/masuda/blog/?p=26</guid>
		<description><![CDATA[一昨日、llfutureという大変コアなイベントでお話させていただく機会を得ました。ハプニングの連続の中、温かい目で見守っていただい方、どうもありがとうございました。
この辺りの話を聞くのは今回が初めてであったという方には、私のプレゼン内容が(メディア)アートと思われてしまうとまずいので、コマーシャルであると断っておきます。プレゼンの最初で口頭でも言い訳していたのですが、ちょっと言葉足らずであったと反省しております。。個人的にはかなり貴重な体験をさせていただいて大満足なのですが、やはりだいぶ役不足感満天でしたね・・。江渡浩一郎さんはとっくの昔にメディアアート作品にRubyを活用しておられましたし、少しでもメディアアート事情を知っていた方には非常に残念な発表となることは流石に自覚しておりましたが、折角お話をいただいたので、えいや！と発表した次第であります。。。。
あともう一点補足です。NON-GRIDさんを中心に企画・制作され、GUIの実装に関わらせていただいたInteractiveMirrorですが、一部でバーチャルで試着できるかのように解釈されてしまっているようですが、そんなことはありませんｗ そんな発言をしたつもりはなかったのですが、、おかしいですね・・　
ところで、これが初めてLLのイベントを見る機会となったのですが、内容が高度過ぎてついていけない話題が多かったもののプレゼン技術の異様に高い方ばかりで楽しませていただきました。InterCommunicationで以前に久保田教授が触れていたライヴパフォーマンスのインターフェースとしての関数型言語(Haskell + SuperCollider)、多分ポイントフリースタイルの簡潔さ辺りを評価しているのではと推測しますが、もしそういった形態のライヴであればいかにも楽しんでいただけそうであると感じました。音楽的知識が皆無過ぎるので言ってみるだけですが！
VJをするなら、fluxusのデモのようにあからさまに副作用あるとピュアじゃないとお叱りを受けそうですので、視覚的な構造は図形言語方式で記述し、時は代入でなくストリームで扱うことになるでしょう。まんま以下の形です:
http://www.ipa.go.jp/jinzai/esp/2005youth/mdata/99-02.html
もう既にどこかにいるような気がしますが、パフォーマーとして誰かがこの道を進んでくれるならすごく見てみたいし、美しいプロセスだと思ってしまうのですが・・。
]]></description>
			<content:encoded><![CDATA[<p>一昨日、llfutureという大変コアなイベントでお話させていただく機会を得ました。ハプニングの連続の中、温かい目で見守っていただい方、どうもありがとうございました。</p>
<p>この辺りの話を聞くのは今回が初めてであったという方には、私のプレゼン内容が(メディア)アートと思われてしまうとまずいので、コマーシャルであると断っておきます。プレゼンの最初で口頭でも言い訳していたのですが、ちょっと言葉足らずであったと反省しております。。個人的にはかなり貴重な体験をさせていただいて大満足なのですが、やはりだいぶ役不足感満天でしたね・・。江渡浩一郎さんはとっくの昔にメディアアート作品にRubyを活用しておられましたし、少しでもメディアアート事情を知っていた方には非常に残念な発表となることは流石に自覚しておりましたが、折角お話をいただいたので、えいや！と発表した次第であります。。。。</p>
<p>あともう一点補足です。<a href="http://non-grid.jp/">NON-GRID</a>さんを中心に企画・制作され、GUIの実装に関わらせていただいた<a href="http://jp.youtube.com/watch?v=QU5DrVu2gdg">InteractiveMirror</a>ですが、一部でバーチャルで試着できるかのように解釈されてしまっているようですが、そんなことはありませんｗ そんな発言をしたつもりはなかったのですが、、おかしいですね・・　</p>
<p>ところで、これが初めてLLのイベントを見る機会となったのですが、内容が高度過ぎてついていけない話題が多かったもののプレゼン技術の異様に高い方ばかりで楽しませていただきました。InterCommunicationで以前に久保田教授が触れていたライヴパフォーマンスのインターフェースとしての関数型言語(Haskell + SuperCollider)、多分ポイントフリースタイルの簡潔さ辺りを評価しているのではと推測しますが、もしそういった形態のライヴであればいかにも楽しんでいただけそうであると感じました。音楽的知識が皆無過ぎるので言ってみるだけですが！</p>
<p>VJをするなら、fluxusのデモのようにあからさまに副作用あるとピュアじゃないとお叱りを受けそうですので、視覚的な構造は図形言語方式で記述し、時は代入でなくストリームで扱うことになるでしょう。まんま以下の形です:<br />
<a href="http://www.ipa.go.jp/jinzai/esp/2005youth/mdata/99-02.html">http://www.ipa.go.jp/jinzai/esp/2005youth/mdata/99-02.html</a></p>
<p>もう既にどこかにいるような気がしますが、パフォーマーとして誰かがこの道を進んでくれるならすごく見てみたいし、美しいプロセスだと思ってしまうのですが・・。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metaphor.co.jp/masuda/blog/?feed=rss2&amp;p=26</wfw:commentRss>
		</item>
		<item>
		<title>jp.nium.display</title>
		<link>http://www.metaphor.co.jp/masuda/blog/?p=25</link>
		<comments>http://www.metaphor.co.jp/masuda/blog/?p=25#comments</comments>
		<pubDate>Sun, 03 Aug 2008 15:51:44 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.metaphor.co.jp/masuda/blog/?p=25</guid>
		<description><![CDATA[jp.nium.displayをちらみしたメモになります。開発中のrev1837の時点を見てフライングで書いているので、予告なしに変更され得る層を紹介しようとしているのかもしれませんし(というのも書いている最中にlistenOnStageが消えたからです！)、逆に周知のことを紹介しているのかも分かりませんが、痒いところに手が届いているあまり興奮を禁じ得ませんでした。その点ご了承下さい。
実は最近になってようやくProgressionを勉強しています。ver3からの入門です(汗)。3本柱の一つであると聞くキャストですが、今まで表示オブジェクトのサブクラス化を好んで行わない(= リンケージしないでインスタンス名つけて操作する)スタイルで制作していたという極めて個人的な理由で食わず嫌いしていたのですが、その考えはすぐに変わることになりました。
リンケージの手間を惜しむ私のような人間には、リンケージ一括設定(特に接尾辞プロファイル！)が以前から提供されていたようですし、開発予定の画面ではなんかキャストのテンプレートを自動生成してくれそうな雰囲気すら漂わせているように見えますが(気のせいでしょうか？)、もしそのようになればキャストのサブクラスを作る負担はかなり減ることになるので期待が膨らんでしまいます。さらにキャストはonCastXXXの処理中に追加したコマンドを同期化してくれるだけかと思っていたものの、実はjp.nium.display系の便利機能を継承していたことを知り、主な機能をチェックしてみようと思ったわけでした。
IEventIntegrator
removeAllListeners(completely:Boolean = false):void
restoreRemovedListeners():void
これら二つを用いて、イベントの配信停止と再開が手軽に実現できるようです。ただし、addExclusivelyEventListenerで追加された場合この限りではないようです。
IExDisplayObject
このインターフェースを実装しているクラスのインスタンスは、jp.progression.casts.*の以下の3つのパッケージ関数によって表示ツリーの階層を問わず簡単に取得できるようです。
getInstanceById(id:String):DisplayObject
表示オブジェクトにidを設定しておくと、階層問わず参照できるようです。getElementByIDみたいですね。
getInstancesByGroup(group:String, sort:Boolean = false):Array
表示オブジェクトにグループ名を設定しておくと、階層問わず集められるようです。
getInstancesByRegExp(fieldName:String, pattern:RegExp, sort:Boolean = false):Array
任意のフィールドで正規表現にマッチした表示オブジェクトを階層問わず集められるようです。例えば、ボタンごとにインスタンス名をつける代わりに以下のように参照することもできそうです。

//同一シンボルを1つしか配置しないため、クラス名からインスタンスが一意に決まる
CastButton(getInstancesByRegExp('className', /^AboutButton$/)[0])
.sceneId = aboutScene.sceneId;

追記: 先ほど試してみたところ、これらの3つのメソッドはaddChildしてステージに追加しなくても使えるみたいです。ということはid設定したら自己責任でexDisplayObject.id = null;などとしてコレクションから消さないとGCされないのかな・・？
setProperties(props:Object):DisplayObject
プロパティの一括設定を行えるようです。CastSpriteの表示アニメーション以前に行う座標などの初期化をすっきりとまとめられそうです。
ExDisplayObject
toBitmapData(transparent:Boolean = true, fillColor:uint = 0xFFFFFFFF):BitmapData
表示オブジェクトの内容をBitmapData化したものを取得します。
以上の操作は、ExLoader, ExMovieClip, ExSprite, ExTextFieldなどで利用できる感じです。このうち、コンテナ系のものであれば以下も利用できる感じです。
IExDisplayObjectContainer 
children : Array
DisplayObjectContainerの子の走査は面倒でしたが、これで随分楽になりそうです。IExDisplayObjectContainerは、必ずしもインデックス値が連続している必要はないため、あらかじめ大きな値を設定しておいて最前面を確保したいときなどに便利そうです。となれば、走査するにあたってnull要素を除いた子のリストが欲しくなるでしょうが、こいつがそれを提供してくれるっぽいです。
contains(child:DisplayObject):Boolean
指定された表示オブジェクトを含むか、自身であればtrueを返します。孫、ひ孫・・とツリー全体をテストしてくれるようです。
removeAllChildren():void
全ての子を削除します。地味に便利です。
最後に、インスタンス化できるものでユニークだなと思った機能に以下があります。
ExSprite
isDragging : Boolean
startDrag()を使用中か否かを返します。
ExMovieClip
isPlaying : Boolean
ムービークリップの再生ヘッドが移動中か取得します。
repeat : Boolean
ループ再生するかを取得または設定できるようです。
switchAtPlaying():void
再生と停止を切り替えます。
ExTextField
appendTextAtCaretIndex(newText:String):void
テキストフィールドのキャレット位置に文字列を挿入できるみたいです。
displayパッケージの機能拡張は継承の苦しい裂目が見えてきて大変な部分だと想像しますが、ここまで使い勝手の優先を貫いていることに感心してしまいました。おかげで、各々の表示キャストはDisplayObjectと同一視できつつ、一方でIExDisplayObjectとしての顔も持つようです。しかし、これもProgressionのごく一部に過ぎないと思うと驚異的ですね！
]]></description>
			<content:encoded><![CDATA[<p>jp.nium.displayをちらみしたメモになります。開発中の<a href="http://progression.libspark.org/browser/branches/Orbiter?rev=1837">rev1837</a>の時点を見てフライングで書いているので、予告なしに変更され得る層を紹介しようとしているのかもしれませんし(というのも書いている最中にlistenOnStageが消えたからです！)、逆に周知のことを紹介しているのかも分かりませんが、痒いところに手が届いているあまり興奮を禁じ得ませんでした。その点ご了承下さい。</p>
<p>実は最近になってようやく<a href="http://progression.libspark.org/">Progression</a>を勉強しています。<a href="http://blog.progression.jp/archives/37">ver3</a>からの入門です(汗)。3本柱の一つであると聞くキャストですが、今まで表示オブジェクトのサブクラス化を好んで行わない(= リンケージしないでインスタンス名つけて操作する)スタイルで制作していたという極めて個人的な理由で食わず嫌いしていたのですが、その考えはすぐに変わることになりました。</p>
<p>リンケージの手間を惜しむ私のような人間には、<a href="http://blog.nium.jp/2007/10/komando.php">リンケージ一括設定</a>(特に<a href="http://blog.nium.jp/LinkageBatchSetting03.gif">接尾辞プロファイル</a>！)が以前から提供されていたようですし、<a href="http://blog.progression.jp/wp-content/uploads/scene_editor.png">開発予定の画面ではなんかキャストのテンプレートを自動生成してくれそうな雰囲気</a>すら漂わせているように見えますが(気のせいでしょうか？)、もしそのようになればキャストのサブクラスを作る負担はかなり減ることになるので期待が膨らんでしまいます。さらにキャストはonCastXXXの処理中に追加したコマンドを同期化してくれるだけかと思っていたものの、実はjp.nium.display系の便利機能を継承していたことを知り、主な機能をチェックしてみようと思ったわけでした。</p>
<h4>IEventIntegrator</h4>
<p>removeAllListeners(completely:Boolean = false):void<br />
restoreRemovedListeners():void<br />
これら二つを用いて、イベントの配信停止と再開が手軽に実現できるようです。ただし、addExclusivelyEventListenerで追加された場合この限りではないようです。</p>
<h4>IExDisplayObject</h4>
<p>このインターフェースを実装しているクラスのインスタンスは、jp.progression.casts.*の以下の3つのパッケージ関数によって表示ツリーの階層を問わず簡単に取得できるようです。</p>
<p>getInstanceById(id:String):DisplayObject<br />
表示オブジェクトにidを設定しておくと、階層問わず参照できるようです。getElementByIDみたいですね。</p>
<p>getInstancesByGroup(group:String, sort:Boolean = false):Array<br />
表示オブジェクトにグループ名を設定しておくと、階層問わず集められるようです。</p>
<p>getInstancesByRegExp(fieldName:String, pattern:RegExp, sort:Boolean = false):Array<br />
任意のフィールドで正規表現にマッチした表示オブジェクトを階層問わず集められるようです。例えば、ボタンごとにインスタンス名をつける代わりに以下のように参照することもできそうです。</p>
<pre class="prettyprint">
//同一シンボルを1つしか配置しないため、クラス名からインスタンスが一意に決まる
CastButton(getInstancesByRegExp('className', /^AboutButton$/)[0])
.sceneId = aboutScene.sceneId;
</pre>
<p>追記: 先ほど試してみたところ、これらの3つのメソッドはaddChildしてステージに追加しなくても使えるみたいです。ということはid設定したら自己責任でexDisplayObject.id = null;などとしてコレクションから消さないとGCされないのかな・・？</p>
<p>setProperties(props:Object):DisplayObject<br />
プロパティの一括設定を行えるようです。CastSpriteの表示アニメーション以前に行う座標などの初期化をすっきりとまとめられそうです。</p>
<h4>ExDisplayObject</h4>
<p>toBitmapData(transparent:Boolean = true, fillColor:uint = 0xFFFFFFFF):BitmapData<br />
表示オブジェクトの内容をBitmapData化したものを取得します。</p>
<p>以上の操作は、ExLoader, ExMovieClip, ExSprite, ExTextFieldなどで利用できる感じです。このうち、コンテナ系のものであれば以下も利用できる感じです。</p>
<h4>IExDisplayObjectContainer </h4>
<p>children : Array<br />
DisplayObjectContainerの子の走査は面倒でしたが、これで随分楽になりそうです。IExDisplayObjectContainerは、必ずしもインデックス値が連続している必要はないため、あらかじめ大きな値を設定しておいて最前面を確保したいときなどに便利そうです。となれば、走査するにあたってnull要素を除いた子のリストが欲しくなるでしょうが、こいつがそれを提供してくれるっぽいです。</p>
<p>contains(child:DisplayObject):Boolean<br />
指定された表示オブジェクトを含むか、自身であればtrueを返します。孫、ひ孫・・とツリー全体をテストしてくれるようです。</p>
<p>removeAllChildren():void<br />
全ての子を削除します。地味に便利です。</p>
<p>最後に、インスタンス化できるものでユニークだなと思った機能に以下があります。</p>
<h4>ExSprite</h4>
<p>isDragging : Boolean<br />
startDrag()を使用中か否かを返します。</p>
<h4>ExMovieClip</h4>
<p>isPlaying : Boolean<br />
ムービークリップの再生ヘッドが移動中か取得します。</p>
<p>repeat : Boolean<br />
ループ再生するかを取得または設定できるようです。</p>
<p>switchAtPlaying():void<br />
再生と停止を切り替えます。</p>
<h4>ExTextField</h4>
<p>appendTextAtCaretIndex(newText:String):void<br />
テキストフィールドのキャレット位置に文字列を挿入できるみたいです。</p>
<p>displayパッケージの機能拡張は継承の苦しい裂目が見えてきて大変な部分だと想像しますが、ここまで使い勝手の優先を貫いていることに感心してしまいました。おかげで、各々の表示キャストはDisplayObjectと同一視できつつ、一方でIExDisplayObjectとしての顔も持つようです。しかし、これもProgressionのごく一部に過ぎないと思うと驚異的ですね！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metaphor.co.jp/masuda/blog/?feed=rss2&amp;p=25</wfw:commentRss>
		</item>
		<item>
		<title>非同期処理いろいろ</title>
		<link>http://www.metaphor.co.jp/masuda/blog/?p=24</link>
		<comments>http://www.metaphor.co.jp/masuda/blog/?p=24#comments</comments>
		<pubDate>Thu, 24 Jul 2008 02:08:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.metaphor.co.jp/masuda/blog/?p=24</guid>
		<description><![CDATA[去年頃から、シングルスレッドかつイベントドリブンなFlash環境で散らかりがちな非同期処理を、すっきりと書けるようにするための試みが多く見受けられるようになりました。それらの特徴をざっと調べてみたメモになります。先駆者達のやり方を広く知り、あわよくば何か洞察を得たいからであって、各ライブラリの優劣を独断と偏見で決定するような主旨ではありません。それからプログラム勉強する前にまず日本語の勉強しろっていうくらい思いやりのない説明が延々続きますが、万が一誰かの参考になればと思い載せておくことにします。
各ライブラリの特徴をつかむため、以下のポイントについて共通で見ていくことにします。


合成
複数の処理を直列化・並列化した複合物を区別なく扱えるか？処理の入れ子はどのように実現されているか？
並列実行
複数の処理の同時実行と、完了の待ち合わせが可能か？
例外処理
エラーハンドラは追加できるか？エラーからの回復は可能か？
続行
エラー発生時に、現在の処理をスキップして、残りの処理を続行することが可能か？
中止
処理の中止は可能か？
値の受け渡し
処理の結果として得られた値を、後続の処理に受け渡す仕組みはあるか？
冗長さ
処理を追加する手順はどうか？クラスを新規に作るのか？クロージャを渡すのか？
動的な処理の追加
処理を追加できる有効なタイミングは？実行後にも処理を追加でき、実行キューのように振る舞うか？
開始トリガ
処理の構築と実行が切り離されていて明示的に開始するのか？それとも構築と同時に暗黙で開始されるのか？
再実行
同じ非同期処理を、2回以上実行可能か？
進捗通知
ロードなどの進捗を通知する枠組みがあるか？
イベントへの適合
完了の通知は、AS3のイベントモデルに準拠して行われるか？
逆に、イベントを各々の非同期処理モデルに適合させる方法は提供されているか？

flashrod Job
var job:Job = new Sequence(
	new Trace("begin"),
	new Concurrent(new URLGet("http://www.google.com/"),
	               new URLGet("http://www.yahoo.com/"),
	               new URLGet("http://www.apple.com/"),
	               [...]]]></description>
			<content:encoded><![CDATA[<p>去年頃から、シングルスレッドかつイベントドリブンなFlash環境で散らかりがちな非同期処理を、すっきりと書けるようにするための試みが多く見受けられるようになりました。それらの特徴をざっと調べてみたメモになります。先駆者達のやり方を広く知り、あわよくば何か洞察を得たいからであって、各ライブラリの優劣を独断と偏見で決定するような主旨ではありません。それからプログラム勉強する前にまず日本語の勉強しろっていうくらい思いやりのない説明が延々続きますが、万が一誰かの参考になればと思い載せておくことにします。</p>
<p>各ライブラリの特徴をつかむため、以下のポイントについて共通で見ていくことにします。<br />
<span id="more-24"></span></p>
<ol>
<li><strong>合成</strong><br />
複数の処理を直列化・並列化した複合物を区別なく扱えるか？処理の入れ子はどのように実現されているか？</li>
<li><strong>並列実行</strong><br />
複数の処理の同時実行と、完了の待ち合わせが可能か？</li>
<li><strong>例外処理</strong><br />
エラーハンドラは追加できるか？エラーからの回復は可能か？</li>
<li><strong>続行</strong><br />
エラー発生時に、現在の処理をスキップして、残りの処理を続行することが可能か？</li>
<li><strong>中止</strong><br />
処理の中止は可能か？</li>
<li><strong>値の受け渡し</strong><br />
処理の結果として得られた値を、後続の処理に受け渡す仕組みはあるか？</li>
<li><strong>冗長さ</strong><br />
処理を追加する手順はどうか？クラスを新規に作るのか？クロージャを渡すのか？</li>
<li><strong>動的な処理の追加</strong><br />
処理を追加できる有効なタイミングは？実行後にも処理を追加でき、実行キューのように振る舞うか？</li>
<li><strong>開始トリガ</strong><br />
処理の構築と実行が切り離されていて明示的に開始するのか？それとも構築と同時に暗黙で開始されるのか？</li>
<li><strong>再実行</strong><br />
同じ非同期処理を、2回以上実行可能か？</li>
<li><strong>進捗通知</strong><br />
ロードなどの進捗を通知する枠組みがあるか？</li>
<li><strong>イベントへの適合</strong><br />
完了の通知は、AS3のイベントモデルに準拠して行われるか？<br />
逆に、イベントを各々の非同期処理モデルに適合させる方法は提供されているか？</li>
</ol>
<p><a href="http://d.hatena.ne.jp/flashrod/20070815#1187191083"><strong>flashrod Job</strong></a></p>
<pre class="prettyprint">var job:Job = new Sequence(
	new Trace("begin"),
	new Concurrent(new URLGet("http://www.google.com/"),
	               new URLGet("http://www.yahoo.com/"),
	               new URLGet("http://www.apple.com/"),
	               new URLGet("http://www.mozilla.org/")),
	new Sequence(new URLGet("http://www.cnn.com/"),
	             new URLGet("http://del.icio.us/")),
	new Trace("wait for 2 sec."),
	new Wait(2000),
	new Concurrent(new URLGet("http://tumblr.com/"),
	               new URLGet("http://flickr.com/")),
	new Trace("end"));
job.start();</pre>
<p>非同期処理の同期化を助ける非常にシンプルな方法です。引数なしのstartメソッドで実行が開始され、完了時にfinishedを送出するものをJobとし、全てのクラスはJobを実装します。たとえ同期処理でも、完了時にfinishedを送出することが求められます。</p>
<ol>
<li>合成可。SequenceやConcurrentはJobインターフェースを実装している。</li>
<li>並列実行可。Concurrentクラスを使う。</li>
<li>エラーについては扱っていない。</li>
<li>続行可。たとえエラーが発生しても、finishedイベントを送出するようJobを実装すればよい。</li>
<li>中止は扱っていない。</li>
<li>値の受け渡しは不可。Job側で結果を保持しておく、などの必要があり。</li>
<li>traceすらもJobの実装クラスになる。クロージャ渡せるようにしたい人は各自でといった感じ。</li>
<li>非同期処理の構築はコンストラクタでのみ行われ、その後の変更は不可。</li>
<li>Job#start()で明示的な実行を行う。</li>
<li>WaitやURLGetを除いた複合非同期処理は再実行不可。一度完了した頃には配列が空になるため。</li>
<li>進捗は通知されない。</li>
<li>完了通知はAS3のイベントモデルに準拠している。イベントからJobを作る汎用メソッドは特にない。</li>
</ol>
<p><a href="http://fladdict.net/blog/2008/01/as3commands.html"><strong>fladdict Command</strong></a></p>
<pre class="prettyprint">var ar:Array = [];
ar.push( new Command(null, trace, ["start serial command"]) );
ar.push( new ASyncCommand(myLoader, myLoader.load, [new URLRequest("URL")],
	myLoader.loaderContent, Event.COMPLETE));
ar.push( new TimerCommand(1000));
ar.push( new XMLLoaderCommand({url:"hogehoge", dataScope:this, dataProp:"dataResult"}))

var command:SerialCommand = new SerialCommand( ar );
command.execute();</pre>
<p>さきほどのものに近いアプローチだと思いますが、いくつか実用的な機能が備わっています。引数なしのexecuteメソッドで実行が開始され、完了時にcompleteを送出するものをICommandとし、全てのクラスはICommandを実装します。たとえ同期処理でも、完了時にcompleteを送出することが求められますが、単に同期処理を追加したいだけであればわざわざクラスを作らずとも、Commandというクラスのコンストラクタにスコープと関数と引数を指定してやるだけで済みます。一方の非同期処理はAsyncCommandでラップでき、Commandと同様のコンストラクタ引数に加えて、イベントディスパッチャと完了を通知するイベント名を指定して作成します。</p>
<ol>
<li>合成可。SerialCommandやParallelCommandはICommandインターフェースを実装している。</li>
<li>並列実行可。ParallelCommandクラスを使う。</li>
<li>エラーについては扱っていない。</li>
<li>続行可。たとえエラーが発生しても、completeイベントを送出するようなCommandを実装すればよい。AsyncCommandを利用する場合、ディスパッチャのエラーイベントについて関知しないことに注意。</li>
<li>ICommand.asを見るに、中止は予定しているように見えるが、未実装と思われる。</li>
<li>値の受け渡しは不可。Command側で結果を保持しておく、などの必要あり。</li>
<li>複合非同期処理の基底クラスであるBatchCommandには各種ショートカットメソッドがあり、後続の処理の追加を簡単にしている。</li>
<li>非同期処理の追加を実行中にもできるが、実行後に追加した処理は開始されないと思われる。</li>
<li>ICommand#execute()で明示的な実行を行う。</li>
<li>複合非同期処理の進捗状況を保存する_indexというカウンタがリセットされないため、再実行は想定していない操作と思われる。</li>
<li>進捗は通知されない。</li>
<li>完了通知はAS3のイベントモデルに準拠している。メソッドとその完了を告げるイベントをワンセットとして非同期処理を表現するAsyncCommandが提供されている。</li>
</ol>
<p><a href="http://mochikit.com/doc/html/MochiKit/Async.html"><strong>Mochikit Deferred</strong></a><br />
JSになってしまいますが、ASへの移植も容易なため紹介します。MochikitのDeferredは以下が大変参考になります。<br />
<a href="http://d.hatena.ne.jp/brazil/20080721/1216580402">http://d.hatena.ne.jp/brazil/20080721/1216580402</a></p>
<p>本家TwistedのDeferredは、スレッドを意識せずプログラムするために生まれたのだと聞きますが、スレッドのないFlashにおいては単にaddEventListenerがアプリケーションコードに直接現れない形で、非同期処理を繋げていく仕組みとして理解することができます。<a href="http://d.hatena.ne.jp/flashrod/20070815#1187191083">Job</a>や<a href="http://fladdict.net/blog/2008/01/as3commands.html">Command</a>に見られる、処理をオブジェクトとしてラップするアプローチに対し、Deferredは関数を直にコールバックチェーンに追加します。そして、callbackの呼び出しにより完了が通知されると、コールバックチェーンの要素を順番に呼び出していきます。呼び出しの結果、戻り値がDeferredであれば非同期処理とみなして残りの実行を後回しに、それ以外であれば同期処理と見なして次のコールバックを呼び出します。</p>
<p>ハンドラの追加は、実行が終わった後になってからも可能で、以下のような微妙な違いがあります。</p>
<pre class="prettyprint">//Mochikit Deferred
var d = new Deferred();
d.callback();
d.addCallback(function() {alert("hoge");}); //呼ばれる

//JSDeferred
var d = new Deferred();
d.call();
d.next(function() {alert("hoge");}); //呼ばれない</pre>
<ol>
<li>合成可。コールバックの戻り値がDeferredの場合、チェーンの実行は一時停止され、子チェーンの完了を待機。</li>
<li>並列実行可。DeferredListを使う。</li>
<li>エラーハンドラはaddErrBackで追加できる。ただし、ErrorEventが送出されたときにerrbackを呼ぶように作っておく必要はある。ハンドラ内で非Errorを返した場合、回復したものとしてコールバックチェーンを再開。</li>
<li>続行可。addBothで、エラーが起こるにせよ起こらないにせよ実行したい後続の処理を追加すればよい。</li>
<li>中止は可。何もしないと、現在の処理を終えてからようやく中止されるが、コンストラクタに適切なキャンセル関数を指定してやれば即座に中止するDeferredを作ることも可。</li>
<li>値はコールバック関数の引数で受け取り、戻り値で後続の処理に引き継ぐ。</li>
<li>クロージャを追加できる。第2引数以降を指定すれば、引数を束縛した関数を追加することもできる。</li>
<li>非同期処理の追加をいつでもできる。実行後であれば、追加した瞬間実行される。ただし、子チェーンであると判明したDeferredには以後コールバックの追加は許されない(Chained Deferreds can not be re-used)。Mochikitの実装でそれを許すと、処理の流れは2本に分岐してしまうからか？</li>
<li>Deferredを返す関数を呼び出して、非同期処理の実行を開始すると同時に、後追いでチェーンを構築するケースが多いと思う(暗黙的開始)。あるいは事前にチェーンを構築してcallbackを呼び出す(明示的開始)。</li>
<li>Deferredは1回しかcallbackが許されない(AlreadyCalledError)。Deferredを返す関数は毎回フレッシュなDeferredを使うのが原則と思われ、そのように実装している限りにおいて再実行は可能といえなくもないが、オブジェクトは再利用できていない。</li>
<li>進捗は通知されない。</li>
<li>完了通知をイベントに戻したければ、誰かにdispatchEventしてもらうことになる。イベントを一度だけリッスンしてDeferredを返す関数を定義しておけば、いろいろと便利になると思われる。</li>
</ol>
<p><a href="http://coderepos.org/share/wiki/JSDeferred"><strong>cho45 JSDeferred</strong></a></p>
<pre class="prettyprint">next(function () {
    alert("1");
}).
next(function () {
    alert("2");
    // child Deferred
    return next(function () {
        alert("3");
    });
}).
next(function () {
    alert("4");
});
alert("0");</pre>
<p>Mochikitの実装をもっとシンプルにできそうなので作ったとのライブラリです。こちらもJSですが、<a href="http://void.heteml.jp/blog/archives/2008/01/asdeferred.html">AS3へ移植したもの</a>もあるようです(並列処理を直列に繋ぐためのショートカットメソッドDeferred#parallelが加えられている点を除き同じかと思わる)。Mochikitとの違いとして、単方向リストを使用したミニマルな実装であること、nextをメソッドチェーンすると最後に追加されたDeferredを指すこと、上の例のように開始は即座でなく同期処理の後に先送りされること(さもないとチェインの構築が間に合わない？)、callやfailによるチェーンの再実行が許可されていること、チェーンの実行後にハンドラを追加しても自動的には実行されないこと、などがあると思います。</p>
<ol>
<li>合成可。コールバックの戻り値がDeferredの場合、<a href="http://f.hatena.ne.jp/images/fotolife/c/cho45/20071207/20071207014817.png">このように</a>チェーンを繋ぎなおす。</li>
<li>並列実行可。Deferred.parallelを使う。</li>
<li>エラーハンドラはerrorで追加できる。ただし、ErrorEventが送出されたときにfailを呼ぶように作っておく必要はある。ハンドラの中で改めてthrowしなければ、回復したものとしてコールバックチェーンを再開。</li>
<li>続行可。エラーが起こる可能性がある処理の後に、何もしないエラーハンドラを追加すればよい。</li>
<li>中止は可。ただし、直列化された非同期処理の中止は、現在実行中のDeferredをライブラリ側で関知してくれないため、少々やりにくいと思われる。</li>
<li>値はコールバック関数の引数で受け取り、戻り値で後続の処理に引き継ぐ。</li>
<li>クロージャを追加できる。引数を束縛させる機能はないので、やりたければ自前でやる。</li>
<li>非同期処理の追加を実行中にもできるが、実行後に追加した処理は開始されないと思われる。</li>
<li>先頭のnextがディレイを噛ませた隙にチェーンを構築するケースが多いと思う(暗黙的開始)。あるいは事前にチェーンを構築してcallを呼び出す(明示的開始)。</li>
<li>チェーン先頭のDeferredを保持しておいて必要なときにcallすれば可。</li>
<li>進捗は通知されない。</li>
<li>完了通知をイベントに戻したければ、誰かにdispatchEventしてもらうことになる。イベントを一度だけリッスンしてDeferredを返す関数を定義しておけば、いろいろと便利になると思われる。</li>
</ol>
<p><a href="http://void.heteml.jp/blog/archives/2008/01/chain.html"><strong>voidelement Chain</strong></a></p>
<pre class="prettyprint">
Chain.parallel({
	foo: { time:5, onComplete:"5000ms" },
	bar: {
		text:"http://www.google.co.jp/",
		onStart:"load text: start",
		onComplete:"load text: complete"
	}
}).
next( function():void {
	trace( this.data.bar );
});
</pre>
<p>JSDeferredのAS実装であるASDeferredをベースに、よく使う処理を簡単に書けるような工夫が施されています。直列処理の追加は、next(function() {...})のような基本的なメソッドに加え、イベントを一度だけ待つlistenや、アニメーションを行うtweenerといった各種ショートカットメソッドを直にメソッドチェーンできるようになっています。並列処理の追加は、辞書を渡すようになっており、それぞれの非同期処理にラベルをつけて結果を後から参照しやすくするついでに、定型的な処理であればそれも辞書で書いてしまおう、といった感じになっています。</p>
<ol>
<li>合成可。コールバックの戻り値がChainの場合、<a href="http://f.hatena.ne.jp/images/fotolife/c/cho45/20071207/20071207014817.png">このように</a>チェーンを繋ぎなおす。</li>
<li>並列実行可。parallelを使う。</li>
<li>エラーハンドラはerrorで追加できる。ライブラリで提供されているChainは、ErrorEventが送出されたときにエラーハンドラが呼ばれるようになっている。ハンドラの中で改めてthrowしなければ、回復したものとしてコールバックチェーンを再開。</li>
<li>続行可。エラーが起こる可能性がある処理の後に、何もしないエラーハンドラを追加すればよい。</li>
<li>中止は可。ただし、直列化された非同期処理の中止は、現在実行中のChainをライブラリ側で関知してくれないため、少々やりにくいと思われる。</li>
<li>値はコールバック関数の引数ではなく、this.dataで受け取り、戻り値で後続の処理に引き継ぐ。戻り値のない処理がチェーンの途中に挟まっても、最後に得たdataを辿れるよう双方向リストになっている。多分。</li>
<li>nextやerrorでクロージャを追加できる他、よく使う処理の追加は専用メソッドで行える。</li>
<li>非同期処理の追加を実行中にもできるが、実行後に追加した処理は開始されないと思われる。</li>
<li>先頭のChain.hogehogeがディレイを噛ませた隙にチェーンを構築するケースが多いと思う(暗黙的開始)。あるいは事前にチェーンを構築してexecuteを呼び出す(明示的開始)。</li>
<li>チェーン先頭のChainを保持しておいて必要なときにexecuteすれば可。</li>
<li>進捗は通知されない。</li>
<li>完了通知をイベントに戻したければ、誰かにdispatchEventしてもらうことになる。ListenerChainを利用すると、イベントから簡単にChainを作れる。</li>
</ol>
<p><a href="http://subtech.g.hatena.ne.jp/secondlife/20080127/1201359890"><strong>secondlife Chain</strong></a><br />
試してみようと思っていたものの、ソースのリンク死んでる模様？?</p>
<p><a href="http://www.libspark.org/wiki/Thread"><strong>beinteractive Thread</strong></a></p>
<pre class="prettyprint">
/* 前略 */

// リサイズ監視用スレッド
new ResizeHandlingThread(context).start();
// 検索制御用スレッド
new SearchControlThread(context).start();
// 初期アニメーション等を行うスレッド
new IntroThread(context).start();
// 3D 制御用スレッド
new PapervisionControlThread(context).start();

/* 後略 */
</pre>
<p>addEventListenerを隠蔽し、非同期処理を同期処理の感覚で書けるライブラリということですが、むしろ状態遷移の多いリアルタイム処理をスマートに書けるようにするためのフレームワークといった感じで、今までのものとはちょっと異質です。個々のThreadは自分の依存するリソースやイベントのことだけ考えればよく、それらの待機は同期処理の感覚で行えるため、時間的しがらみを超えてコントローラを分割できるようになります。また、ロード中やオーバー待ちといった状態を一つのメソッドと対応付けできるので、状態遷移図を素直にコードに落とし込むようにしてプログラムが書けるのもメリットの一つかと思います。</p>
<ol>
<li>合成可。SerialExecutorやParallelExecutorはThreadを継承している。</li>
<li>並列実行可。ParallelExecutorを使う。</li>
<li>エラーハンドラはerrorで追加できる。第一引数には補足するエラーの型を、第二引数にハンドラを指定。ハンドラが設定されていなかったり、ハンドラ中にさらにエラーが起きれば、親スレッドに伝播。ハンドラが無事終了すると回復したものとしてエラーが発生する前に実行されていた実行関数から再開するが、ハンドラ内でnextを呼び出した場合はそこから再開。</li>
<li>続行可。<a href="http://www.libspark.org/svn/as3/Thread/tags/v1.0/samples/flickrsphere/src/org/libspark/flickrsphere/threads/flickr/LoadFlickrPhotoImagesThread.as">このように</a>する。SerialExecutorが途中でこけたとき、無視して続行するにはどうするんだろう？</li>
<li>中止はinterruptで可。ただし、割り込みハンドラを設定していない状態で待機中のThreadを中止しようするとInterruptedErrorとなる。自作Threadを中止に対応させるにはcheckInterruptedで割り込みされたか調べて行う。</li>
<li>値の受け渡しというか保持は、Threadごとの実装となる。例えば、URLLoaderThreadはloaderを保持する。それとは別に、遅延リソースの生産者と消費者を結合させないために<a href="http://www.libspark.org/htdocs/as3/thread-files/document/#monitor-system">Monitor</a>が使える。</li>
<li>スレッドを使うためのスレッドを書かなければいけないケースがほとんどだと思われる。まるでネズミk(ry</li>
<li>だんだん質問に答える意味がよく分からなくなってきたが、SerialExecutorのaddThreadは実行中にもできると思うけど実行後に追加した処理は開始されないと思われる。</li>
<li>Thread#startで開始。</li>
<li>startは一度しか呼び出せないので、新規のスレッドを作って再実行する。</li>
<li>進捗はIProgressを実装した各種Threadからイベントで通知される。それらのトータルの進捗を通知してほしければ、それぞれをMultiProgressにaddProgressしてやる。ただし、重みを指定する必要があるので、ファイルサイズの比は事前に調べておく。</li>
<li>Threadを使っていろいろと処理した後に、続きの処理はイベントドリブンにしたいとか万が一あれば、EventDispatcherThreadを継承してdispatchEventする感じになると思われる。eventメソッドで特定のイベントが起きるまでThreadを待機させることができる。ただし、nextメソッドによって次の実行関数が設定された場合は待機しない。これをうまく利用して、<a href="http://www.libspark.org/browser/as3/Thread/trunk/samples/autoShowHide/AutoShowHideThread.as">読みやすい状態マシン</a>を書くこともできるようだ。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.metaphor.co.jp/masuda/blog/?feed=rss2&amp;p=24</wfw:commentRss>
		</item>
		<item>
		<title>HoC spectrum</title>
		<link>http://www.metaphor.co.jp/masuda/blog/?p=21</link>
		<comments>http://www.metaphor.co.jp/masuda/blog/?p=21#comments</comments>
		<pubDate>Fri, 18 Jul 2008 16:32:36 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.metaphor.co.jp/masuda/blog/?p=21</guid>
		<description><![CDATA[House of Cardsのデータで遊んでみました:
http://www.metaphor.co.jp/2008/07/visualization-of-spectrum-radiohead-house-of-cards/
マウスを動かすとアングルが変わるのですが、顔を横から見たときにサウンドスペクトルになっています。
勢いに任せたひどいソースは以下:
source code
GoogleCodeで提供されているCSVそのままだとちょっと重いので、上のソースに含まれているcsv2binary.rbを使っていろいろと都合のいいバイナリファイルに変換しています。具体的には:

「頂点数, X, Y, Z, 明度, X, Y, Z, 明度, X, Y, Z, 明度・・・」 の繰り返しの並び
フレームを間引く (デモでは1フレ飛ばしでデータを作り、15fpsで再生)
明度が低い頂点を捨てる (デモでは60以下を捨てたため髪の毛がない)
X, Y, Zは適当に16bitにおさめる
モデルの中心あたりに原点を移動

Flash側はそれをロードし、ByteArrayから頂点情報を読み出して描画という感じです。音に同期させるため、(フレームレートに依存しない)再生時間を元にByteArray中の目的とするフレームを指すpositionを計算しています。
追記:
いちから解説をするべきでしょうが、以下に非常にシンプルなコードが紹介されていたため割愛します！
RadioheadのプロモーションがGoogle Codeで行われている理由
さらに追記:
今改めて未読消化してみるとFlash版の挑戦者はたくさんおられたようです。日付を見るにとても仕事速い！
http://blog.r3c7.net/?p=209
http://nutsu.com/blog/2008/071720_radiohead.html
http://aquioux.blog48.fc2.com/blog-entry-446.html
迷わず頂点を減らした私はなんだか反則してしまったような気持ちです。。
]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.google.com/creative/radiohead/">House of Cards</a>のデータで遊んでみました:<br />
<a href="http://www.metaphor.co.jp/2008/07/visualization-of-spectrum-radiohead-house-of-cards/">http://www.metaphor.co.jp/2008/07/visualization-of-spectrum-radiohead-house-of-cards/</a></p>
<p>マウスを動かすとアングルが変わるのですが、顔を横から見たときにサウンドスペクトルになっています。<br />
勢いに任せたひどいソースは以下:<br />
<a href="http://www.metaphor.co.jp/masuda/blog/wp-content/uploads/2008/07/hoc-spec.zip">source code</a></p>
<p>GoogleCodeで提供されているCSVそのままだとちょっと重いので、上のソースに含まれているcsv2binary.rbを使っていろいろと都合のいいバイナリファイルに変換しています。具体的には:</p>
<ul>
<li>「頂点数, X, Y, Z, 明度, X, Y, Z, 明度, X, Y, Z, 明度・・・」 の繰り返しの並び</li>
<li>フレームを間引く (デモでは1フレ飛ばしでデータを作り、15fpsで再生)</li>
<li>明度が低い頂点を捨てる (デモでは60以下を捨てたため髪の毛がない)</li>
<li>X, Y, Zは適当に16bitにおさめる</li>
<li>モデルの中心あたりに原点を移動</li>
</ul>
<p>Flash側はそれをロードし、ByteArrayから頂点情報を読み出して描画という感じです。音に同期させるため、(フレームレートに依存しない)再生時間を元にByteArray中の目的とするフレームを指すpositionを計算しています。</p>
<p>追記:<br />
いちから解説をするべきでしょうが、以下に非常にシンプルなコードが紹介されていたため割愛します！</p>
<p><a href="http://as3s.org/archives/2008/07/radiohead-google-code.html">RadioheadのプロモーションがGoogle Codeで行われている理由</a></p>
<p>さらに追記:<br />
今改めて未読消化してみるとFlash版の挑戦者はたくさんおられたようです。日付を見るにとても仕事速い！</p>
<p><a href="http://blog.r3c7.net/?p=209">http://blog.r3c7.net/?p=209</a><br />
<a href="http://nutsu.com/blog/2008/071720_radiohead.html">http://nutsu.com/blog/2008/071720_radiohead.html</a><br />
<a href="http://aquioux.blog48.fc2.com/blog-entry-446.html">http://aquioux.blog48.fc2.com/blog-entry-446.html</a></p>
<p>迷わず頂点を減らした私はなんだか反則してしまったような気持ちです。。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metaphor.co.jp/masuda/blog/?feed=rss2&amp;p=21</wfw:commentRss>
		</item>
		<item>
		<title>Stream.as</title>
		<link>http://www.metaphor.co.jp/masuda/blog/?p=20</link>
		<comments>http://www.metaphor.co.jp/masuda/blog/?p=20#comments</comments>
		<pubDate>Mon, 14 Jul 2008 05:16:35 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.metaphor.co.jp/masuda/blog/?p=20</guid>
		<description><![CDATA[前回の方向でStreamを再実装してみる。ただしそのままだとつまらないのでStreamをオブジェクト風にしてみる。nullを空ストリームを表すために使ってしまうとメソッドチェーンに失敗する可能性が出てくるので、StreamのサブクラスであるNullStreamを定義し、メソッド呼び出しに対して何もしないよう実装する。

enum(0, 100).filter(function():Boolean {return false;}).forEach(trace); // => (何も起きない)
trace(enum(0, 100).filter(function():Boolean {return false;})); // => [object NullStream]

([]).forEach(trace);と同様な挙動と言われれば当たり前と思うかもしれない。
今のところ最低限のことしか実装してないけど、やはりこっちのアプローチの方があっちよりシンプルかも・・？
勉強ため、ソースの中で解説してみる:

//Stream.as
package masda.stream {
  public class Stream {
    private var _car:Object;
    private var _cdr:Function;

//Streamの実体は、先頭要素(car)と残りのStreamを返す関数(cdr)。
    public function Stream(car:Object, cdr:Function/*delayed object*/) {
      _car = car;

//毎回cdrを評価するのはコストがかかるので、
//memoProcで元の関数の戻り値をキャッシュする関数を得る(後述)。
      [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.metaphor.co.jp/masuda/blog/?p=17">前回</a>の方向でStreamを再実装してみる。ただしそのままだとつまらないのでStreamをオブジェクト風にしてみる。nullを空ストリームを表すために使ってしまうとメソッドチェーンに失敗する可能性が出てくるので、StreamのサブクラスであるNullStreamを定義し、メソッド呼び出しに対して何もしないよう実装する。</p>
<pre class="prettyprint">
enum(0, 100).filter(function():Boolean {return false;}).forEach(trace); // => (何も起きない)
trace(enum(0, 100).filter(function():Boolean {return false;})); // => [object NullStream]
</pre>
<p>([]).forEach(trace);と同様な挙動と言われれば当たり前と思うかもしれない。</p>
<p>今のところ最低限のことしか実装してないけど、やはりこっちのアプローチの方が<a href="http://www.metaphor.co.jp/masuda/blog/?p=7">あっち</a>よりシンプルかも・・？<br />
勉強ため、ソースの中で解説してみる:</p>
<pre class="prettyprint">
//Stream.as
package masda.stream {
  public class Stream {
    private var _car:Object;
    private var _cdr:Function;

//Streamの実体は、先頭要素(car)と残りのStreamを返す関数(cdr)。
    public function Stream(car:Object, cdr:Function/*delayed object*/) {
      _car = car;

//毎回cdrを評価するのはコストがかかるので、
//memoProcで元の関数の戻り値をキャッシュする関数を得る(後述)。
      _cdr = memoProc(cdr);
    }

//carはそのまま返す。
    public function get car():Object {
      return _car;
    }

//cdrはアクセスされて初めて評価される。
    public function get cdr():Stream {
      return _cdr(); //force
    }

//forEachは終端を表すnilでない限りcdrを辿り、carをコールバックに渡す。
//再帰で書くとスタックオーバーフローするので反復で書くことにする。
    public function forEach(proc:Function):void {
      var s:Stream = this;
      while (s != nil) {
        proc(s.car);
        s = s.cdr;
      }
    }

//StreamからArrayにするには、戻り値にする配列にバインドされたpushをforEachに渡すだけ。
    public function toArray():Array {
      var ary:Array = [];
      forEach(ary.push);
      return ary;
    }

//要素の参照もforEachの要領で行う。
    public function ref(n:uint):Object {
      var s:Stream = this;
      while (s != nil &#038;& n > 0) {
        s = s.cdr;
        n--;
      }
      return s.car;
    }

//mapは、carにそれを写像したものを置き、
//cdrが要求されたときに残りをmapしたStreamを返すようなStreamを返す。
//自身がnilならnilを返す。
    public function map(proc:Function):Stream {
      if (this == nil) return nil;

      return new Stream(proc(car), function():Stream {
        return cdr.map(proc);
      });
    }

//filterは、carに述語を満たす要素を置き、
//cdrが要求されたときに残りをfilterしたStreamを返すようなStreamを返す。
//スタックオーバーフロー対策のために、述語を満たすまでwhileによる要素のスキップを行う。
    public function filter(pred:Function):Stream {
      var s:Stream = this;
      var e:Object;
      while (s != nil) {
        e = s.car;
        if (pred(e))
          return new Stream(e, function():Stream {
            return s.cdr.filter(pred);
          });
        s = s.cdr;
      }
      return nil;
    }

//メモ化関数は、引数に指定した関数の戻り値をキャッシュするような関数を返す。
    private static function memoProc(proc:Function):Function {
      var alreadyRun:Boolean = false;
      var result:Object = false;
      return function():Object {
        if (alreadyRun) return result;

        result = proc();
        alreadyRun = true;
        return result;
      }
    }
  }
}
</pre>
<pre class="prettyprint">
//nil.as
package masda.stream {
//nilはNullStreamの唯一のインスタンスとする。
  public var nil:NullStream = NullStream.getInstance();
}
</pre>
<pre class="prettyprint">
//NullStream.as
package masda.stream {
//NullStreamはStreamのサブクラス。
  public class NullStream extends Stream {
    private static var instance:NullStream;

//NullStreamはシングルトン。
    public static function getInstance():NullStream {
//インスタンスを遅延初期化。
      instance = instance || new NullStream(new PrivateKey());
      return instance;
    }

//carにnullを置き、Stream#refでインデックスが範囲外のときにはnullが返るようにする。
//cdrが要求されたら自身を返すようにする。
    public function NullStream(key:PrivateKey) {
      super(null, next);
    }

    private function next():Stream {
      return this;
    }
  }
}

//このファイル内でのみ可視なクラスを、コンストラクタをこじ開ける鍵として使う。
class PrivateKey {};
</pre>
<pre class="prettyprint">
//list.as
package masda.stream {
//引数を要素とするストリームを作成する関数。
  public function list(...args):Stream {
//引数が底つきたらnilを返して終わりを告げる。
    if (args.length == 0) return nil;

//引数は、cdrにアクセスされるたびにそのcarに消費されて短くなる。
    return new Stream(args.shift(), function():Stream {
      return list.apply(null, args);
    });
  }
}
</pre>
<pre class="prettyprint">

//enum.as
//startから始まり、stopを含む数までをstepの間隔で並べたストリームを返す。
//stopを省略すると無限リストになる。
package masda.stream {
  public function enum(start:Number = 0, stop:Number = NaN, step:Number = 1):Stream {
    function numbersStartingFrom(n:Number, step:Number):Stream {
      return new Stream(n, function():Stream {
        return numbersStartingFrom(n + step, step);
      });
    }

    function enumerateInterval(start:Number, stop:Number, step:Number):Stream {
      if ((step > 0 &#038;& start > stop) || (step < 0 &#038;& start < stop)) return nil;

      return new Stream(start, function():Stream {
        return enumerateInterval(start + step, stop, step);
      });
    }

    return isNaN(stop) ?
      numbersStartingFrom(start, step) :
      enumerateInterval(start, stop, step);
  }
}
</pre>
<p># 文章を書くのが滅多にないためか、文体がコロコロ変わっちゃいますな。。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metaphor.co.jp/masuda/blog/?feed=rss2&amp;p=20</wfw:commentRss>
		</item>
		<item>
		<title>stream-cons</title>
		<link>http://www.metaphor.co.jp/masuda/blog/?p=17</link>
		<comments>http://www.metaphor.co.jp/masuda/blog/?p=17#comments</comments>
		<pubDate>Sun, 13 Jul 2008 22:42:14 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.metaphor.co.jp/masuda/blog/?p=17</guid>
		<description><![CDATA[SICPのストリームの定義がかっこよくてしびれました。
例えば引数に指定した数から始まる整数列を返す手続きはSICPだと:

(define integers-starting-from n
  (stream-cons n (integers-starting-from (+ n 1))))

これをAS3でやると多分こんな感じになる:

function integersStartingFrom(n:uint):Stream {
  return new Stream(n, function():Stream {
    return integersStartingFrom(n + 1);
  });
}

自分が以前似たようなことをやったときは、同様の関数が以下のような醜い姿に:

function count(start:uint):Iterable {
  return new Iterable(function():Function {
    var i:uint = start;
    return function():uint {
      return i++;
  [...]]]></description>
			<content:encoded><![CDATA[<p>SICPのストリームの定義がかっこよくてしびれました。</p>
<p>例えば引数に指定した数から始まる整数列を返す手続きはSICPだと:</p>
<pre class="prettyprint">
(define integers-starting-from n
  (stream-cons n (integers-starting-from (+ n 1))))
</pre>
<p>これをAS3でやると多分こんな感じになる:</p>
<pre class="prettyprint">
function integersStartingFrom(n:uint):Stream {
  return new Stream(n, function():Stream {
    return integersStartingFrom(n + 1);
  });
}
</pre>
<p>自分が以前似たようなことをやったときは、同様の関数が以下のような醜い姿に:</p>
<pre class="prettyprint">
function count(start:uint):Iterable {
  return new Iterable(function():Function {
    var i:uint = start;
    return function():uint {
      return i++;
    };
  });
}
</pre>
<p>遅延リストの構造を「次の要素を返す関数を返す関数」から「cdrが遅延評価されるconsセルを使ったリスト」にしただけでこれだけのシンプルさが得られるなら、<a href="http://www.metaphor.co.jp/masuda/blog/?p=7">あれ</a>をもう一度書き直してもいいような気がしています、またいつか！</p>
<p>以下余談:</p>
<p>AS3は特殊形式を扱えないので遅延評価させたい式はいちいち無名関数で包むことになりますが、まあそれは仕方がないとして、末尾最適化がない（ですよね？）のでちょろっと再帰しただけで即スタックオーバーフローするのが終わっています。従って、ストリームの操作の中にはwhileと代入の形に翻訳せねばならないものがあるのが残念なところです。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metaphor.co.jp/masuda/blog/?feed=rss2&amp;p=17</wfw:commentRss>
		</item>
	</channel>
</rss>
