-?> と .?.

nilを返す関数

こんな階乗関数を書いたとします。

(defn fact [n]
  (when (>= n 0)
    (loop [n n acc 1]
      (if (< n 2)
	acc
	(recur (dec n) (* acc n))))))

最初に引数チェックを行い、引数が0以上の時のみ処理をおこないます。引数が負数だと何もせず何も返さないので評価値は nil になります。

(fact 10) ;=> 3628800
(fact -1) ;=> nil

これを使ってプログラムを組んでみました。

(-> 10 fact inc (str " finished"))
;;=> "3628801 finished"

(-> -1 fact inc (str " finished"))
;;=> java.lang.NullPointerException ...

階乗の結果をインクリメントして、その結果に finished をくっつけたものが式全体の評価値になります。二つめの例では fact に渡されるのが負数のため fact の評価値が nil になり、次の inc で null例外が発生しています。

そこで -?> を使う

こういう場合に -?> を使うと例外発生を抑制できます。

(use '[clojure.contrib.core :only (-?>)])

(-?> 10 fact inc (str " finished"))
;;=> "3628801 finished"

(-?> -1 fact inc (str " finished"))
;;=> nil

 -?> を使うと式の途中で評価値 nil になった時点で評価を終了し、全体の評価値が nil になります。上の例では fact の結果が nil に成ったところで評価が終了しています。その後の inc や str は評価されません。
なお評価値に nil が現れなけば、-?> は -> と同じ結果になります。

一方 -?>> は用意されていませんでした。-?> を真似れば自分で作れそうな気がします。どちらかというと -> よりも ->> のほうが使う場面が多いので -?>> の方がむしろ必要かもしれません。

でもこれ必要?

どうもこの -?> を使う状況というのは好ましくない状況に思えます。
「どこかで nil になるかもしれないけど、隠蔽しちゃえ」ということですから、それってなんかエラー管理がいい加減な気がするのですが。
ある種の脱出ロジックには使えるかもしれませんが、それもちょっと好ましいコードとは言えないですよね。

.?. もあるよ。

javaメソッドのチェーンを行う「..」に対応した「.?.」もあります。
こちらは -?> よりも使える場面が限られていそうです。