Callback DSL on Haxe

Preview:

DESCRIPTION

Frontrend FukuokaでLTした資料です

Citation preview

Callback DSL on Haxe

by Technical Rockstars CTO @nobkz

自己紹介

Technical Rockstars CTO

tw : @nobkz

Haxe/JS/C#/Java/Objective-C++

好きな言語:Lisp(Common Lisp, Gauche)/Haskell/OCaml/Prolog

福岡Haxe勉強会主催

Haxe?

Haxe

いろんな言語にコンパイルできる (to Flash, C++, C#, JS, PHP, Java, NekoVM)

強力な型システム(型推論など)

強力なマクロ

-@nobkz

“これから

HaxeでDSL作った話しをします”

なぜHaxeでDSLを 実装したか?

-@nobkz

“ある日のことでした”

–@nobkz

“それはHaxeでnodeとか

seleniumのテストを書いていました。”

@nobkz

そいつは、いつのまにか

ぶくぶくと大きくなってました。

コールバック地獄例

僕はコールバック地獄に 悩まされていました

ある日のこと…

僕は最高の3大エンタメ (まどまぎ、ボルテ、Scheme)の一つ、

Schemeを楽しんでいた。

–@nobkz

“ん?コールバックて CPSスタイルだよね….”

CPSスタイル(Scheme)

–@nobkz

“そういえばHaskellに継続モナド ってあったよなぁ。”

http://www.sampou.org/haskell/a-a-monads/html/contmonad.html

そして僕は気づいた

–@nobkz

“そうだ! 継続モナドを同様の仕組みで

DSLを創れば良いんだ!”

継続モナドの利用

コールバック地獄 -> CPSスタイルに似ている?

コールバックを継続モナドで表現する

それを、合成すれば良いんじゃないか?

方針

1 . とりあえず、モナドの結合ができるようにする

2. do記法をつくる

3. コールバックDSLをつくる

そしていろいろあって

実装しました。 (この点については

次回のHaxe勉強会で話します)

結局できたもの

Before

Before

After

After

なんということでしょう!

結果

簡単になった!

コールバックのネストが無くなった。

構文のノイズが無くなって読みやすい!

ただ、ボイラープレートが残っている感。

けどちょっとだけ、 実装の仕組みについて

(時間が無ければ飛します)

Monad?

Monad

言語内DSLを構築するための仕組み

モジュールの組み合せ方

背景に数学的な理論がある(圏論)

Optionモナド作成

Option(Maybe)型について

Option(HaskellではMaybe)型をつくる

data Maybe a = Just a | Nothing

Haxeではenumで実現

HaxeのEnumについて

enumはCの列挙体とはちょっとちがう

コンストラクタがパラメータを持つことができる

enumの例

enum MyNumber{ Zero; Plus(i:Int); Minus(i:Int); } !var x : MyNumber = Zero; var y : MyNumber = Plus(10); var z : MyNumber = Minus(10);

EnumでOptionの実装

型パラメータとEnumでOptionを作った。

enum OptionDef<T>{ None; // Nothing of Haskell Some(i:T); // Just of Haskell }

returnとbind

モナドで必要に関数は2つ

Mが対象のデータ型だとする

return :: A -> M A

>>= :: M A -> (A -> M B) -> M B

これらの関数がモナド則を満すように実装する

Haxeでのreturnとbind

クラスメソッドとして実装する

returnだと、返り値のreturnと混合するので、mPackとした。

>>=はmBindとした。

Optionのreturnとbindの型定義

Option型のクラスをつくり、クラスメソッドとして実装する

Option.mPack<A> : A -> OptionDef<A>

Option.mBind<A,B> : OptionDef<A> -> ( A -> OptionDef<B> ) -> OptionDef<B>

実装

class Option{ public static function mPack <A>(a : A) : Option<A> return Some(a); ! public static function mBind <A,B>(m : OptionDef<A>, f : A -> OptionDef<B>) : OptionDef<B> return switch(m){ case Some(a) : f(a); case None : None; }; }

returnとbindを組み合わせ

モナドの計算はbind(>>=)とreturnで組織する

Haskell の例:return 10 >>= (\x -> return x >>= (\y -> return x >>= (\z -> return (z + x + y))))

Haxeでのモナドの計算

Haxeのある機能をつかわないとやりづらい

Option.mBind(Option.mPack(10),function(x) return Option.mBind(Option.mPack(x), function(y) return Option.mBind(Option.mPack(y),function(z) return Option.mPack(x+y+z))));

しかるある機能を使うと途端に楽になる

using!

using Option; !10.mPack().mBind(function(x) return x.mPack().mBind(function(y) return y.mPack().mBind(function(z) return (x + y + z).mPack())));

usingを使うと第一引数が、なんと、メソッドを呼び出すオブジェクトみたいに!

HaxeでOptionモナドを実装した

とりあえず、Haxeでも十分にモナドの計算ができる!

次に継続モナドだが、次回Haxe勉強会で

Haxeのdo記法の実装

前提知識:Haxeのマクロ

Haxeのマクロ(黒魔法とも呼ばれる)は新しい構文を定義することができる

マクロでdo記法をつくる

構文木はEnum

Haxeの構文木はEnumで表現されている。

1 + 1の構文木は次の様にHaxeで表わせる

1 + 1の構文木

{ expr : EBinop(OpAdd, { expr : EConst(CInt(1)), pos : #pos(Sample.hx:10: characters 6-7) }, { expr : EConst(CInt(2)), pos : #pos(Sample.hx:10: characters 10-11) }), pos : #pos(example/Sample.hx:28: characters 6-11) }

構文木を書き代える

Haxeのマクロは構文木を書き代えることができる

構文木を書き代えることによって、別の表現を与える事ができる

例 : 1 + 1を引き算にする

macro public static function toSub(e){ return switch (e.expr) { case EBinop(OpAdd, a, b): macro $a - $b; case _: e; } } !!toSub(1 + 1); // => 0

マクロでdo記法を実装

詳しくは次回Haxe勉強会で説明します

これから先は次回Haxe勉強会にて!

Haxe勉強会やんお!

2月のどっかやんお!

福岡でやんお!

詳細は、@nobkzで流れまう!

Callback DSL &

Monad Frameworks のこれから

これから

liftのなどのモナド関数に実装

読みやすいDSLを目指す

LinqみたいなDSLの実装

公開するお!

ご清聴ありがとうございました! @nobkz

Recommended