📝Clojure Flows

📝Clojure Flows

Clojureのフロー制御まとめ.

Clojure Flow Basic Syntax #

フロー制御の基礎シンタックス.

  • if
  • when
    • true判定.
  • if-let
    • letで定義したロジック判定のシンボルをifでテストする.
    • これは,たとえば複雑な真偽判定のロジックにシンポルを割り当てることで可読性を上げるために利用できる.
    • when-letもある.
  • cond
    • 複数のifを書くときのわかりやすい記法.
    • 条件に当てはまらない場合の処理をelseで実施することができる.
  • case
    • condにおいて判定する値が1つしかない場合.

🔎if-let は処理の結果による分岐でつかう #

if-letはマクロでありC言語の邪悪な習慣をエレガントにしたとか😕

なにかの処理をして戻り値がnilか否かで処理を分岐するときにエレガントな書き方ができる. 具体的にはlet とifで以下なものを,

(let [result (proc)]
  (if result
    (do-something result)
    (do-else)))

if-letだと以下のようにかける.

(if-let [result (proc)]
  ((do-something result)
    (do-else)))

Java的には関数を処理して異常の場合は戻り値に -1とかfalseとか戻さずに例外を上げるのがベストプラクティスだけど関数型でも同じなのだろうか?そしてこの 関数の呼び出し元に分岐を判断させるのがC言語の邪悪な習慣といっているのだろうか?いずれにしろこういう戻り値にnilをつかって呼び出し元を困らせる邪悪な関数につかう.

ref. 💡例外がないと戻り値チェックでウンコード

まあif-letやwhen-letはnilが戻るような副作用のある関数の呼び出しの文脈で利用するものと心得ておこう.

Clojure:副作用の繰り返し(dotimes/doseq/for) #

Clojure - Clojureを学ぼう - フロー制御

  • dotimes
    • 式n回評価, nilを返す.
  • doseq
    • シーケンスに対して順列に繰り返す.
    • 遅延シーケンスは評価を強制.
    • nilを返す.
    • 複数のシーケンスに対しはforEachのように振る舞う.
  • for

💡Clojureの繰り返し: map vs doseq(for) #

どちらもシーケンスに対する処理を実施する.

副作用があるときにdoseq(for)を利用する, そうでないときにmapを利用する.

なるべく副作用がないようにプログラミングを構築するというClojureの考えとしてはdoseqよりもmapのほうが登場回数が多い.

mapは関数をすぐには適用せずに遅延シーケンスを構築する. 実際に中の値の評価をするにはdoall, intoなどの方法が必要.

(doall (map coll))
(into [] (map coll))
(into-array (map coll))

リスト内包表記(for)はmap/filterよりもhuman-readableという利点はある. 以下は同じである.

(for [number [1 2 3]] (* number 2))
(map #(* % 2) [1 2 3])

シンプルな変換処理を有限なリストに適用するならばmap/filterよりもみやすいかもしれない(Pythonではmap/filterよりもリスト内包表記がよくつかわれる).

ひとつのシーケンスに複数の変化を施すならば遅延シーケンスを扱うmapに利点がある. 複数のシーケンスを順番に従って取り出して扱うならばforのほうが読みやすい(cf. mapcat, juxt).


Active Recalls #

Clojureにおけるif-letとはなんですか?またその目的はなんですか? #

letで定義した真偽値をifで評価する.

複雑なロジックにシンボルを割り当てることで可読性を上げるため.

Clojureで複数のifをするときのシンタックスシュガーはなんですか? #

cond, case.

Clojureで副作用がある繰り返しの3つのシンタックスなんですか?また戻り値はなんですか? #

dotimes, doseq, for.

戻り値はnil.