ActionScript3でカリー化(引数束縛)
少し前にJavaScriptのこことかここでネタにされたカリー化をas3でやってみた
試したコードはこんな感じ。
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()"> <mx:Script> <![CDATA[ import mx.controls.Alert; import flash.utils.setTimeout; Function.prototype.curry = function (... rest):* { var args:* = rest; var self:* = this; return function (... rest):* { rest = args.concat(rest); return self.apply(this, rest); }; }; private function init():void { function sum(x:int, y:int):int { return x + y; } function mean3(a:int, b:int, c:int) : int { return (a + b + c) / 3; } trace( sum.curry(10)(15) ); // 25 trace( mean3.curry(10)(20, 30) ); // 20 trace( sum.curry(10).curry(20)() ); // 30 trace( mean3.curry(10).curry(20)(30) ); // 20 trace( sum.curry(10, 20)() ); // 30 } private function showMessage(massage:String):void { Alert.show("ぼたんくりっく" + massage, "Message", Alert.OK); } private function clickHandler(event:Event):void { setTimeout(showMessage.curry(event.currentTarget.label), 2000); } ]]> </mx:Script> <mx:Button x="10" y="10" label="ボタンA" id="btnA" click="clickHandler(event)"/> <mx:Button x="80" y="10" label="ボタンB" id="btnB" click="clickHandler(event)"/> </mx:Application>
実行するためにはコンパイラオプション-strictをOFFにしないとビルドが通りませんが一応希望する動作になっているようです。
他言語での利用例でよく使われるイベントハンドラのコールバックに渡すクロージャに関してはFlexのイベントモデルはたいていコールバックにパラメータを渡す事が出来るので無理に使わなくても困る事ないんだけどね...
setTimeoutの例にしても第三引数にパラメータ配列を渡せるので普通に記述可能ですが、関数のバリエーションやコンボを作るってケースではそれなりに有効な気がします。