気持ちよくAndroidを書くために

ちょっとでもJava7なAndroidを気持ちよくプログラミングしたい、
Javaっぽい(?)ところがありつつもモダンなパラダイムが取り入れられているScalaが羨ましく見えたので、Scalaっぽく書きたいという意志から書いています
サンプルコードでは紙面の都合上、retrolambdaでlambda式使っています

## Scalaの羨ましいところ

挙げればキリが無いですが、以下とします

- 関数型プログラミング
- 強力な式

## 関数型プログラミングっぽく

これについては[Roppongi.aar #2 - connpass](http://roppongi-aar.connpass.com/event/21907/)で私が[発表した内容](https://speakerdeck.com/petitviolet/write-android-like-scala)がベースとなっています

OOなjavaで無理して関数型プログラミングを目指すのではなく、関数型プログラミングの中でもモナドといわれる便利なデータ構造を便利に使いたい、といった程度のものです

そこで、Androidでもモナド実装して使えば気持ちいいんじゃないか、ということで簡単なライブラリにしました
[petitviolet/Android-Monad](https://github.com/petitviolet/Android-Monad)
なおモナド則を満たしているかのチェックは行っていませんが、その点はご了承下さい

RxJavaを使えば関数型プログラミングっぽく書くことも出来ますが、ここでは話しません

### 使い方

mavenにアップロードしてあるのでこれで利用できます

```groovy:build.gradle
compile 'net.petitviolet.android:monad:0.5.0'
```

いまサポートしているのは以下です

- Maybe
- ListM
- State

### Maybe

いわゆるMaybeモナドで、nullセーフなプログラミングを実現するためのものです
`Maybe`モナドのいいところとして、中身が`null`であってもそうでなくても全く同じように一連の処理を適用した結果として`Just`か`None`が得られるため、`@nullable`な値に対するボイラープレート的nullチェックを無くすことが出来る点が挙げられます

`Maybe.of`のファクトリーメソッドで初期化して、それに対して便利メソッドが生えているので、メソッドチェーンで処理を続けていくのが想定される使い方です
例えばDBへの`Maybe`なselectを行い、ヒットするものがあった場合のみ処理を続行する、というの綺麗に書けたりします

```java
Maybe<Integer> maybeInt = Maybe.of(x);
maybeInt.flatMap(i -> findById(i))  // Maybe<Data> findById(int n)
        .map(Data::getCost)  // int getCost()
        .filter(j -> j > 300)
        .foreach(k -> Log.d(TAG, "result: " + k));
```	

`@nullable`なものはとりあえず`Maybe`でくるんでしまえば安全に操作することが出来るようになります

### ListM

リストモナドですが、Scalaっぽいコレクション操作が出来るようになっています

```java
ListM<Integer> listM = ListM.unit();
listM.addAll(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
ListM<String> result = listM.filter(i -> i % 3 == 0)
        .flatMap(i -> ListM.<Integer>of(i * 10))
        .map(s -> s + "!");
        .foldRight((a, acc) -> a + ", " + acc, " <= end");
// result -> 90!, 60!, 30!, <= end
```

`List`インタフェースをimplementしてあるので、便利な`List`として使えるイメージです

Androidっぽい例として以下のようなものがあります
`ViewGroup`の中から`EditText`を`findViewById`してきて入力が空でないものについて、`Integer`に変換して合計値を求める、といった処理がさらっと書けるようになります

```java
int sumOfInput = ListM.of(viewGroup1, viewGroup2,...)
    .map(l -> ((EditText) l.findViewById(R.id.input)))
    .map(editText -> editText.getText().toString())
    .filterNot(s -> TextUtils.isEmpty(s))
    .map(Integer::parseInt)
    .foldLeft(0, (acc, i) -> acc + i);
```

### State

Stateモナドです
一連の処理の中で状態変数を共有することが出来るものとなっています
State自体は状態を使った処理を記述するもので、`apply`に初期状態を渡すことで処理が走って結果が得られるようになっています
一応作った程度なので例がちょっと微妙ですが、以下のように使えます

```java
Tuple<Integer, List<String>> result = State.<List<String>, Integer>unit(1)
        .map(i -> i + 10)
        .map(i -> i * 2)
        .flatMap(integer -> State.init(new Function.F1<List<String>, Tuple<Integer, List<String>>>() {
            @Override
            public Tuple<Integer, List<String>> invoke(List<String> strings) {
                if (integer % 2 == 0) {
                    strings.add("awesome");
                    return Tuple.of(integer, strings);
                } else {
                    strings.add("Oops");
                    return Tuple.of(-100, strings);
                }
            }
        })).apply(new ArrayList<>());
// result._1 == 22;
// result._2 == ["awesome"];
```

## 強力な式

scalaにはjavaよりも強力で便利な式がいくつかあります
それを無理やりjavaでもそれっぽく使えるようにしたライブラリを作りました
[petitviolet/Android-scaex](https://github.com/petitviolet/Android-scaex)

#### 使い方

同じくmavenにアップロードしてあるのでdependenciesに追加すれば使えます

```groovy
dependencies {
    compile 'net.petitviolet.android:scaex:0.1.1'
}
```


### if式

javaの`if`は文ですが、scalaの`if`は式です
そもそも値を返せる点で大きく異なります
`if`の条件分岐によって値を得たい場合、javaなら以下のように書きます

```java
int target = //...;
String sentence;
if (target > 10) {
    sentence = "large";
} else if (target > 5) {
    sentence = "medium";
} else {
    sentence = "small";
}
```

if-elseだと三項演算子で簡潔に書けますが、条件が複雑になれば見辛くなり、else ifを使いたい場合だとそもそも使えなかったりします

そこで、`IF`を使うと以下のように書けます

```java
String sentence = IF.<String>x(target > 10).then("large")
         .ElseIf(x > 5).then("medium")
         .Else("small");
```

単純に行数が減って多少見やすくなりました
ジェネリクスとして`String`を渡すのが冗長でやや不満が残る点ですね
渡さないと`Object`になってしまうので、現状はやむを得ない対応となっています

また`then`には引数を0個受け取って処理を実行して値を返す`Function.F0`を渡せるようにしてあるため、複雑な処理を行うことも出来ます

```java
String sentence = IF.<String>x(x > 10).then("large")
        .ElseIf(x > 5).then(() -> {
            Log.d(TAG, "nice if-expression");
            return "medium";
        })
        .Else("small");
```

### pattern match

関数型プログラミングとも紐づく特徴ですが、scalaにはpattern-match(match-case)が実装されています
これと同じことをjavaでするには残念ながらif文しかないわけですが、`Match`を使うとちょっとそれっぽく書けます

```java
abstract class Hoge {
    abstract public String call();
}

class Foo extends Hoge {
    public String call() {
        return "foo";
    }
}

class Bar extends Hoge {
    public String call() {
        return "bar";
    }
    public String shout(){
        return "yeah!";
    }
}

private void some(Hoge hoge) {
    Match.<String, Hoge>x(hoge)
            .Case(Foo.class).then(Hoge::call)
            .Case(Bar.class).then(h -> ((Bar)h).shout())
            .eval("Not Matched!");
}
```


`Case`に`Foo.class`とclassオブジェクトを渡していたりcastしているのがわりと微妙ですが、何となくmatch-caseっぽいことを実現できています
`Case`の中にclassオブジェクトを渡せばパターンマッチのようにその型チェックを実行し、`boolean`を渡せばguardとして機能します
`eval`にはデフォルト値としてマッチしなかった場合の返り値を渡すことも出来ます。

# まとめ

モナドとpattern-match作ったのに、do式(for式)が無くて片手落ち感はんぱないですね
自作ライブラリの宣伝みたいになってしまいましたが、関数型プログラミングをjavaで実現するためのライブラリとかは他にもあります
例) [Functional Java](http://www.functionaljava.org/)

現状はscala書いているとその表現力によって簡潔に書けたりするのが、javaだから...と諦めて冗長に書かざるを得ない状況が辛いので、ちょっとでも簡潔に綺麗に書けるようになれば幸いです
とにかく早くjava8来てくれ、という思いです