個人事業主になったので真面目にアウトプットしてみるブログ

フリーで顧客の会社に潜り込んでAndroidアプリつくって、とりあえず食っていけるようにアウトプットを増やしていくブログです。

Androidプログラマの関数型プログラミング勉強振り返り

関数型プログラミングがわからなかった。

  • 遅延評価がわからなかった(なにそれおいしいの?)
  • 純粋関数がわからなかった(こわせるよ?)
  • 参照透過性がわからなかった(オブジェクト指向のストラテジーとかに似てる?)
  • 副作用がわからなかった(結局副作用ってなんのことを指すの?)
  • ラムダがわからなかった(関数の参照・・・コールバックだよね?)
  • 高階関数がわからなかった(メソッドチェーンで書くシーケンシャルな処理だよね?)
  • イミュータブルがわからなかった(コンフリクトおきない?)
  • 状態がなくなるがわからなかった(結局状態は必要では?)
  • 宣言的がわからなかった(どれも宣言的といえなくはない?)

今はなんとなくわかる。

  • 遅延評価は、今、その処理の実行をする必要ないけど今書ける処理として書いておくやつ。書かれている場所と実行タイミングが異なって、メモリに優しい書き方。けどやりすぎる評価されるタイミングが重なって辛いとか、色々ありそう。
  • 入力が同じだったら純粋関数は結果が変わらない関数。自分でそうつくらないといけない。なので関数外のスコープの変数を参照してはいけない(やらないと無理な時もあるかも)。純粋関数もJavaにかかればあっという間に壊せる。なので出来るだけJavaよりはKotlinを選んで、末端までイミュータブルなデータを利用する。一応Stringも普通に扱えばImmutable。data classは積極的に使おう。普通のclassのインスタンスを純粋関数に代入しては壊れる元。
  • 透過参照性は組み替えても処理の全体的な性質が変わらなようにできるようなもの。純粋関数のみで構成し、うまく使うことで戦略的な組み替えが可能になる。べつに戦略的につくらなくてもいい。純粋関数でボトムアップとしてつくれば結果的透過参照性のある処理のかたまりができる(だよね?)
  • 副作用は純粋関数以外のもので構成され、他影響を与えるもの。つまりクラスのメンバ変数の参照や代入によって他の処理、次の処理の結果がインプットは同じなのに変わる可能性があるもの。同じスコープ関数の外にある変数に値を再代入することを破壊的代入、もしくは自殺行為という。ただしクロージャ的なものはスコープ外で宣言しないとできないし、クロージャへの参照のスコープを限定的にすれば、その関数(スコープ)の外からみれば純粋関数。外から見て純粋かというのは大事かも?DBやFileのIOや通信結果も副作用といえばそう。その失敗や一定の値を返さない事によって他の処理の期待値が壊れて不協和音、システムの破壊につながるような処理は副作用。適切にリトライなり、冪等的にロールバックしたり、結果をエラーハンドリングに流すなりして、全体的にはあらかじめ決められた処理として動いていれば問題ない。イメージ的には正の数の時はこの関数、負のときにはこの関数、結果的にプロットされる全体像がみえていればいい。みたいな感じ。かな?
  • ラムダは遅延評価をさせるもの。もしくは遅延評価を前提にした透過参照的に宣言された大きな処理、再利用性の高い処理への組み込み単位。カリー化などを使って部分適用を利用しながらラムダ内の評価タイミングを遅らせながらラムダを評価する材料をあつめるみたいな段階的なことも可能。変数のように扱えるので、プログラムの表現方法が格段にあがる。ただし評価される時のオーバーヘッドが通常の処理よりあるのでJavaやKotlinにはあるので注意。必然的な部分にとどめないともっさりするかも?関数が第一級、参照として扱えるみたい話もラムダのこと。
  • 高階関数は関数が引数だったり、返り値が関数になるような関数のこと。JavaやKotlinだとラムダのこと。ラムダを引数にしたり、ラムダをかえすようなものをいう。カリー化は後者の良い例で、filter/map/zipみたいなやつが前者の良い例。前者は遅延評価を前提としていて、実際には必要になった時だけそのラムダが評価される。別に作っていけないわけではないので必要だとおもったら作るのが普通。別にモナドには高階関数がいくつかあることが条件にあるけどモナドを作る必要はない。(モナドはしらないでもプログラムはある程度できる、スタイルの問題だったり、作らなくても自然とつかっていたりするかも)
  • イミュータブルはどんなタイミングでみても全く同じであること。コレクション(リスト、マップ、セット)や構造体(すべてfinalでメンバ変数を定義したDTOみたいなもの、data classなど)。その値を変更する場合は必ず別のインスタンスにシャローコピーを施しながら、変更したい値だけを入れ替える。data classでいうとcopy関数で簡単にそれが可能。イミュータブルでないものは、addやremoveが可能なコレクションや、varで宣言されたフィールドが存在するclassなど。ただし。
val printlist: (List<Int>) -> (() -> Unit) = { list -> {
    println(list)
} }
printlist(mutableListOf(1, 2, 3))()

みたいにListに対してMutableList(変更可能なリスト)を渡すことができるので、Kotlinでのリストは実質イミュータブルなものはない。リードオンリーになるので、正確なイミュータブルなリストを使いたい場合はEclipse Collectionsを使うと良いらしいよ。

残り二つは時間の都合でまたこんどー。

Android界隈でKotlin Coroutinesの登場によってRxJavaが不要と言われる原因とそれに対する反論

ちまたでKotlin Coroutinesの登場でRxJavaが不要になりつつあるという噂が流れているみたいなので、どう言う状況なのかまとめてみました。

さっき書いたこの記事

pooh3-mobi.hatenablog.jp

まぁ論拠は薄いし、そんなデータそろえてって、みんながすげー納得するようなことを一朝一夕でやるなんて、データサイエンティストさんに失礼ですよ。マナー違反ですね。 ということで、とりあえず前提としてRxJavaは通信ライブラリであるRetrofitとセットで広がったものでリアクティブプログラミングをやろうと思って使っていた人はほとんどいなかった!(衝撃的事実)という前提で話を展開していくとします。

続きを読む

FRPとReactive Extensions

FRPとReactive Extensions

Rx(Reactive Extensions)はFRPではないとい批判を聞く事がありますし、オライリーから出ているRxJavaの書籍(英語版)の説明にも似たようなことが書かれています。

参考:「Reactive Programming with RxJava: Creating Asynchronous, Event-Based Applications」

しかし一方で広義ではそれらもFRPを実現するためのスタイルの一つとして認める話もあります。FPR界隈からみるとRxは厳密性には欠けるが、FRPからインスパイアされたものであるという表現が正しいという見方もあるようです。

続きを読む

RxJavaは通信系ライブラリ(Retrofit)とセットだったという事実について

何言ってんだお前。 RxJavaはリアクティブプログラミングのためのライブラリであって、通信系のライブラリじゃねーよ。

はいごもっともとです。

それに・・うん、してった。

でなんでこんな話をしたかというと、RxJavaでリアクティブプログラミングなんかやろうとする人が少なかったんじゃないかという仮説が突然浮かんだので現実を見つめようとおもいました。

続きを読む

関数名、メソッド名でgetXXXがダメな理由

ダメである理由

getという単語は、その単語自体がその中で何をしているのかを隠してしまうので、容易に誤解が発生してしまいやすいこと。
・同じオブジェクトからは同じ値が返ってくるという勘違いが発生する恐れがある
・一部のおじさんにはgetter/setterもつ、特異なクラスをイメージさせてしまう
 →別の問題へ派生する可能性が出る:必要もないのにsetを用意しマルチスレッドで扱われるときにその邪悪さの効果を発揮する。すなわち複数で参照され得に参照するスレッドが異なっているときに、setを使ってしまう事で、別のスレッド側ではたまに起きる(たまたまタイミングが一致したときだけ)のような、発見が難しいバグとなって現れる。

よく言われる代替案

・単純な参照ではない場合
 →load/fetch/find/request/など実際の処理がイメージしやすい命名を選ぶ
・単純な参照の場合
 →System.currentTimeInMillis()のように直接参照しているようなイメージになるようにする
 or→finalかつ非privateな値として宣言しgetterをはさまず直接参照する

getしか使いようがないが、getをそのまま使うと誤解が発生するケースの代替案
・言葉としてgetしか使いようがない場合、オンメモリ上の参照でNullが発生する可能性がある場合
 →getXXXOrNull()
・言葉としてgetしか使いようがない場合、対象の存在がオンメモリ上ではなく外部に依存していて、Nullがあり得る場合
 →getXXXIfExist()


まとめ

絶対に使わないとするとすごく難しい問題が出てくる。しかしできるだけ防ぎたい問題である。

Javaのマルチスレッド間の値の変更と参照についてメモ

すべてはここから始まった?

のでとりあえず気になるとろを調べて。あーだいたいおkって感じのところまで。

続きを読む