Hatena::ブログ(Diary)

mooz deceives you

(about 'mooz) ; => "See http://mooz.github.com/index-ja.html"

 | 

November 21 (Sun), 2010

ES Harmony の Proxy について #fxdevcon で LT してきました

LT on Firefox Developer Conference 2010

Firefox Developers Conference 2010ECMAScript Harmony の Proxy について LT させて頂きました.

発表資料

発表に使った資料を SlideShare にアップロードしました. 途中, Harmony を Harmoney と書いているところが多々ありますが, やさしく見過ごしてやって下さい.

追記 (2011 2/23 21:01)

スライド中,以下のように has (in 演算子に対応) が第一引数に Proxy のインスタンスを受けとるような書き方をしてしまっていますが,これは誤りです.

Proxy.create({
    has: function (p, name) { }
});

Proxy.create({
    has: function (_, name) { }
});

has の場合は,以下のように第一引数に直接 name が来ます.

Proxy.create({
    has: function (name) { }
});

詳しくは no title を参照して下さい.

経緯

およそ二週間ほど前のことになりますが, id:Constellation さん経由で Firefox 4 に Proxy が実装されているということを知りました.

「こいつはすごい」としこたま感動していたところ, Mozilla の dynamis さんにお誘い頂き LT をさせて頂くことに.

そんなこんなで, はじめての LT を大人数の前で行うことになったわけです.

Proxy

発表資料は時間の関係で Proxy の説明自体が簡素なものとなってしまいましたが, 今ここで細部に関して分かりやすい説明を行う自信もありませんので, 興味のある方は no title を覗いて頂ければと思います.

以下, 発表で紹介した関数 + α のコードです.

not.js

in 演算子のオーバーロードが出来ると知り, 以前から気に食わなかった if (!(prop in obj)) { ... } という書き方を何とかしようということに.

実装は以下の通りで, 非常に簡単です.

function not(obj) {
    return Proxy.create({
        has: function (name) {
            return !(name in obj);
        }
    });
}

これで if (prop in not (obj)) と書けて嬉しいですね, という話だったのですが, 微妙な失笑のようなものを頂くに終わりました.

括弧省略したいです.

safe.js

こちらは比較的実用的な例となったかと思います. が, 実際に使うかと問われれば……

function safe(obj, def, delimiter) {
    delimiter = delimiter || "$";
    def = arguments.length >= 2 ? def : void 0;

    return Proxy.create({
        get: function (_, name) {
            return digSafe(obj, name.split(delimiter), def);
        }
    }, Object.getPrototypeOf(obj));
}

function digSafe(obj, props, def) {
    if (!props.length)
        return def;

    var cur = obj;
    var target = props.pop();

    for (var i = 0, len = props.length; i < len; ++i) {
        var prop = props[i];
        if ((cur instanceof Object || typeof obj === "object") && prop in cur)
            cur = cur[prop];
        else
            return def;
    }

    return cur[target];
}

safe(obj).foo$bar$baz のようにして . の代わりに $ をプロパティアクセス演算子として使用するため, $ で始まるプロパティが参照できないという弊害がありますが, これは $$ を $ とみなすことで回避できます. コードを簡素にするため上記の例ではやっていません.

maybe.js

safe に関して, Twitter

や,

という意見を頂きました.

元々 safe は MayBe という名前で,

return maybe(obj).foo.bar.baz.$;

として使うようになっていたのですが, キモさが足りないということで発表の三日前にコードを書き換えた次第です.

ということで, 元々の maybe を載せておきます.

function maybe(obj, def, endSign) {
    endSign = endSign || "$";
    def = arguments.length >= 2 ? def : void 0;

    return Proxy.create({
        get: function (_, name) {
            if (name === endSign)
                return obj;
            else if ((obj instanceof Object || typeof obj === "object") && name in obj && obj !== def)
                return maybe(obj[name], def, endSign);
            else
                return maybe(def, def, endSign);
        }
    });
}

こちらの方が定義としてはすっきりしていますし, Haskell っぽいので個人的にはお気に入りです.

最後に

最後に, Firefox Developer Conference 2010 の感想を簡単にですが.

生 John Resig を見ることができ感動でした. また, Shibuya.js な方々の発表がどれもぶっ飛んでおり, 興奮モノでした. 個人的に興味のある「処理系」に関する話題が多かったのが良かったです.

途中, 隣に座っていた人の画面をチラりと見たところ Firefox ステータスバーにカタツムリのアイコンを発見するというイベントもあり, 休み時間になって勇気を出し「作者です」と話しかけ, それから色々とお話することが出来たりしました. 懇親会においても KeySnail 使ってますと話しかけてきて下さった方がいたりと, 作者冥利に尽きるといったところです.

Mozilla をはじめとする関係者の方々, 毎年素晴らしいイベントを開催して下さりありがとうございます.

 |