HaxeのOptionをScalaっぽくする


null書いたら負け。そんなあなたにオススメなのが、[Option](http://api.haxe.org/haxe/ds/Option.html)です。

Optionを使うことで、nullの値を取る場合の処理が、いい感じに書けるのですが、如何せんhaxe.ds.Optionでは物足りなさを感じてしまいます。

そこで、HaxeのOptionをScalaのOptionっぽく使えるよう、拡張してみました。
ScalaのOptionのメソッドを全て実装するのは面倒なので、個人的に良く使うものを選んで実装しました。

ScalikeOptionクラスに、静的なメソッドを定義して、
あとはusingを使ってScalikeOptionのメソッドを呼ぶだけ、とても簡単。

```Haxe
import haxe.ds.Option;

using ScalikeOption;

class ScalikeOption {
    public static function isEmpty<T>(opt:Option<T>) {
        return switch(opt) {
            case Some(v): false;
            case None: true;
        }
    }

    public static function isDefined<T>(opt:Option<T>) {
        return !opt.isEmpty();
    }

    public static function getOrElse<T>(opt:Option<T>, defValue:T) {
        return switch(opt) {
            case Some(v): v;
            case None: defValue;
        }
    }

    public static function map<A, B>(opt:Option<A>, f:A -> B) {
        return switch (opt) {
            case Some(v): Some(f(v));
            case None: opt;
        }
    }

    public static function fold<A, B>(opt:Option<A>, defValue:B, f:A -> B) {
        return opt.map(f).getOrElse(defValue);
    }

    public static function iter<A>(opt:Option<A>, f:A -> Void) {
        switch(opt) {
            case Some(v): f(v);
            case None: 
        }
    }

    public static function flatten<T>(opt:Option<Option<T>>) {
        return switch (opt) {
            case Some(v): v;
            case None: None;
        }   
    }

    public static function flatMap<A, B>(opt:Option<A>, f:A -> Option<B>) {
        return switch (opt) {
            case Some(v): 
                switch(f(v)) {
                    case Some(w): Some(w);
                    case None: None;
                }
            case None: None;
        }      
    }
} 

```

ScalaのOption.foreachは値を返さず副作用のみなのに対して、HaxeのLambda.foreachはBool値を返すので、ちょっと違います。Haxeで値を返さず副作用のみを取るのは、Lambda.iterなので、それにならい、ScalaのOption.foreachに対応するメソッドはScalikeOption.iterとしました。

ScalaのOption.getは、個人的に使っちゃいけないものだと思っているので、追加しませんでした。



使い方はこちら

```Haxe
import haxe.ds.Option;

using ScalikeOption;

class Sample {
    static var s = Some(1);
    static var n = None;
    static var ss = Some(s);
    static var sn = Some(n);

    public static function main(){
        trace("Some.getOrElse(0): " + s.getOrElse(0));
        trace("None.getOrElse(0): " + n.getOrElse(0));
        trace("Some.isEmpty: " + s.isEmpty());
        trace("None.isEmpty: " + n.isEmpty());
        trace("Some.isDefined: " + s.isDefined());
        trace("None.isDefined: " + n.isDefined());
        trace("Some.map: " + s.map(function(a) { return a * 10;}));
        trace("None.map: " + n.map(function(a) { return a * 10;}));
        trace("Some.fold: " + s.fold(99, function(a) { return a *10;}));
        trace("None.fold: " + n.fold(99, function(a) { return a *10;}));
        s.iter(function(a) { trace("Some.iter: " + a); });
        n.iter(function(a) { trace("None.iter: " + a); });
        trace("Some(Some).flatten: " + ss.flatten());
        trace("Some(None).flatten: " + sn.flatten());
        trace("Some.flatMap: " + s.flatMap(function(a) { if(a == 1) { return Some("one"); } else { return None;} }));
        trace("None.flatMap: " + n.flatMap(function(a) { if(a == 1) { return Some("one"); } else { return None;} }));
    }
}
```

ihxでこれを実行すると、

```Bash
>> Sample.main(); 
Sample.hx:12: Some.getOrElse(0): 1
Sample.hx:13: None.getOrElse(0): 0
Sample.hx:14: Some.isEmpty: false
Sample.hx:15: None.isEmpty: true
Sample.hx:16: Some.isDefined: true
Sample.hx:17: None.isDefined: false
Sample.hx:18: Some.map: Some(10)
Sample.hx:19: None.map: None
Sample.hx:20: Some.fold: 10
Sample.hx:21: None.fold: 99
Sample.hx:22: Some.iter: 1
Sample.hx:24: Some(Some).flatten: Some(1)
Sample.hx:25: Some(None).flatten: None
Sample.hx:26: Some.flatMap: Some(one)
Sample.hx:27: None.flatMap: None
```

といった具合になります。


ちょっとしたものですが、nullのないコードが少しは書きやすくなると思います。
nullのないコードに幸あれ！