2009年11月25日
AS3 でメソッドチェーンしたくなる話
いろんな AS3 のサンプルが掲載されていて楽しい ActionSnippet | paste it in your timeline - or in your constructor で Functions Returning Functions が紹介されていた。
シンプルで美しいのだけど、ソースに1箇所無駄があったので省いてみたものを紹介する。
// Functions Returning Functions (Revised) // original: http://actionsnippet.com/?p=2430 // - Removed line variable by using arguments.callee. package { import flash.display.Sprite; public class FlashTest extends Sprite { public function FlashTest() { var connect:Function = function(xp:Number, yp:Number, col:uint=0):Function{ graphics.lineStyle(0,col); graphics.moveTo(xp, yp); return function(xp:Number, yp:Number):Function{ graphics.lineTo(xp, yp); return arguments.callee; }; } // draw a triangle connect(200,100)(300,300)(100,300)(200, 100); // draw a box connect(100,100, 0xFF0000)(150,100)(150,150)(100, 150)(100,100); } } }
このサンプルがやってることは非常にシンプルで、connect()
関数を呼び出すと、lineTo
するだけの関数が返ってくる。この関数を呼ぶと、さらに自分自身が返ってくるので、connect(200,100)(300,300)(100,300)(200, 100);
のように順番に呼び出していくと三角形が描けてしまうわけだ。
このサンプルはやり過ぎにしても、ActionScript の標準ライブラリではメソッドチェーンやりたいと思うことが度々ある。昔はあまり思わなかったんだけど、jQuery や Ruby などに慣れてくると、他の場所でもメソッドチェーンしたくなる病にかかる。
たとえば lineTo
は
// (注) 実際にはこのように書くとエラーになります graphics.beginFill(0xff0000) .moveTo(200,100) .lineTo(300,300).lineTo(100,300).lineTo(200, 100) .endFill();
のように書けたら嬉しいし、あの憎き Matrix
も
// (注) 実際にはこのように書くとエラーになります var mtx:Matrix = Matrix .identity() .rotate(Math.PI) .scale(2, 2);
とできると immutable になってかなり嬉しい。
かといって、このあたりを丸々ラップしなおすのは面倒なので、結局文句いいながら使い続けてる。他力本願。