イテレータの使いどころ (vimperatorのソース読書会?)
ブックマークは溜めるばかりでは意味がないですね。たまには検索をして引き出さないと。
一年半前ほどにつけたブクマで思わぬ拾い物をした。
- JavaScript 1.7 の yield が凄すぎる件について - IT戦記
- Latest topics > JavaScript 1.7のyield文ってなんじゃらほ - outsider reflex
今現在作っているFirefoxの拡張(textarea/input 要素を vim っぽくする拡張)はvimperatorのソースを参考に作っている(パクっているとも言える)のだけれど、New in JavaScript 1.7 - MDCに書かれているイテレータが良く出てくる。
訳も分からず作っていたわけだけど上二つのページを見つけてやっと理解できてきた。
vimperatorのソースにはクラスとそれを管理するクラスのパターンが3つある。
vimperator.Map
クラスとvimperator.Mappings
クラスvimperator.Command
クラスとvimperator.Commands
クラスvimperator.Option
クラスとvimperator.Options
クラス
管理クラス側のパブリックな場にはadd
,get
メソッドと__iterator__
メソッドが共通してある。
そして、プライベートな場に、オブジェクトを蓄積する配列とイテレータオブジェクトを返す関数がある。
簡略化したソースで示すと
function Class(name){ this.name = name; }; fuction ManagerClass(){ // private var array = []; function iterator(){ for (var i=0; i<array.length; i++){ yield array[i]; } throw StopIteration; } // public var manager = { __iterator__: function(){ return iterator(); }, add: function( obj ){ array.push(obj); }, get: function( name ){ for (var i=0; i<array.length; i++){ if ( array[i].name == name ) return array[i]; } return null; } }; return manager; }
な感じになっていて、
var manager = new ManagerClass(); manager.add( new Class('hoge') ); manager.add( new Class('foo') ); manager.add( new Class('bar') );
というふうにオブジェクト化されている。
で、for (var obj in manager)
で回すとobjには何が入ってくるかっていうと、add
,get
メソッドじゃなくて、追加したClassのオブジェクトが入ってくる。add
,get
メソッドは得られない。半分隠蔽している感じだ。
順を追って書くと、for (var obj in manager)
で回すと
- managerの中に__iterator__メソッドがあるのでそれが実行される。
- __iterator__メソッドはiterator関数を実行する。
- iterator関数は
yield
があるのでイテレータオブジェクトを返す。 - __iterator__メソッドはイテレータオブジェクトを返す。
- めでたくイテレータとして繰り返される
ManagerClassにgetAll
みたいなメソッドを定義して
var objs = manager.getAll(); for (var i=0; i<objs.length; i++){ .... }
みたいにやるよりスマートなコードが書けるわけだ。
イテレータの初歩かもしれないけれど、僕は感動したのでここに長々と書いてみた。
……というのが、ジェネレータの使いどころなんだと思う。僕は頭が悪いんで、有効に活用できる場合というのを自分ではさーっぱり思いつかないんだけど。なので、せめて、頭のいい人がこの解説みたいな文章を見てyieldの有効な使い道をたくさん考えてくれることを期待します。
Latest topics > JavaScript 1.7のyield文ってなんじゃらほ - outsider reflex
別に僕の頭が良いんじゃなくてvimperatorを作った人が良いんだけれど、これが解にならないかなと1年半前のpiro氏に返信してみる。