cond

8章4節のcondについて。
条件判断といえば、自分はif式よりもこっちばっかり使ってるな。
たぶんThe Little Schemerのせい。
condも知らないことが結構あった。

(cond
  (条件式1 条件式1が#f以外の値になった場合のcond式の値)
  (条件式2 条件式2が#f以外の値になった場合のcond式の値)
  ...
  (条件式n 条件式nが#f以外の値になった場合のcond式の値)
  (else 条件式が全て#fになった場合のcond式の値))

「条件式1」から順に評価していって、「条件式i」が#f以外の値だったら、ただちに「条件式iが#f以外の値になった場合のcond式の値」返す。
これもやっぱり最後の

(else 条件式が全て#fになった場合のcond式の値)

は省略可能で、すべての条件式が#fになった場合にelseの式が省略されていた場合はGaucheでは#を返すそうだ。
Schemeではこれも未定義なのかな。


cond節内の「条件式iが#f以外の値になった場合のcond式の値」は省略可能だそうだ。
例えば

(cond
 (条件式)
 (else 条件式が#fの場合のcond式の値))

みたいのも書けるそうだ。
条件式が#f以外になれば条件式の値がそのまま使われる。
さらに、elseの部分も削除して

(cond (条件式))

も文法上OKらしい。実際使うのかは甚だ疑問。


今まで「条件式」の値は捨ててたけど、

(条件式 条件式が#f以外の値になった場合のcond式の値)

の部分を

(条件式 => 条件式が#f以外の値になった場合に評価される手続き)

のように書いて、後で利用することもできるそうな。condで初めて知ったことその2。
「条件式が#f以外の値になった場合に評価される手続き」に渡される引数は「条件式」の値。
読んでるときは、一瞬、(゚д゚)ハァ?と思った。
条件式を満たしたんだから、渡される引数は常に#tじゃねーのかよ!と。


ずっと「#f以外の値」と奥歯に物がはさまったような言い方をしてたけど、実はSchemeでは#f以外の値は全て真とみなされるらしい。
18ページに書いてあった。ここらへんはしっかり読んでなかったもんなー。(ノ∀`)タハー
C言語で0以外の値が真になるのと似てるな。


ってことで、
「リストの中に奇数があれば、初めに見つかった奇数を2倍して返し、すべて偶数だったら0をかえす」みたいなのは

(cond
  ((find odd? lis) => (lambda (x) (* 2 x)))
  (else 0))

と書けるんだと。
わー、便利!...なのか?よくわからん。


さらに、condには以下のような書き方もあるそうだ。

(条件式 判断式 => 判断式が#fになった場合に評価される手続き)

condで初めて知ったことその3。
まず「条件式」を評価して、その値が「判断式」に渡されて、「判断式」の結果が#f以外の値になれば「判断式」の値を「判断式が#fになった場合に評価される手続き」に渡して、その結果をcond式の値とする。
ややこし!ややこしすぎるよ!
便利なんだろうけど、使う局面を想像できない。
この使い方の例が本に無いので、自分で適当に使ってみた。...かったけど、SRFI-61がGaucheでサポートされてないっぽい?

gosh> (use srfi-61)
*** ERROR: Compile Error: cannot find file "srfi-61.scm" in *load-path* ("/usr/local/share/gauche/site/lib" "/usr/local/share/gauche/0.8.14/lib")
"(stdin)":1:(use srfi-61)

Stack Trace:
_______________________________________

だと。
ヽ(`Д´)ノ ンギャー

追記 2009/02/28

SRFI-61はuseしなくても使えるそうだ。
id:SaitoAtsushiからコメントで指摘をいただいた。
ってことで、やってみた。

gosh> (cond
       (1 even? => (lambda (x) (print x " is even.")))
       (2 odd? => (lambda (x) (print x " is odd.")))
       (#f (lambda (x) #t) => (lambda (x) (print "always right.")))
       (3 number? => (lambda (x) (print x " is number.")))
       (else (print "nothing is right.")))
always right.
#<undef>

うん。使えた。

(条件式 判断式 => 手続きオブジェクト)
の書式の説明の箇所に
「この仕様はSchemeにはありませんが、SRFI-61で規定された拡張です」って書いてあったので、srfi-61をuseしなければ、と先入観があった。
39ページには確かに「代表的な組み込みのSRFIライブラリ」として紹介されてるわぁ ><


しかし、「条件式」って言い方はおかしいと思う。
「条件式」の値が#fになっても、必ず「判断式」に値が渡されて、判断は「判断式」の値に基づいて行われるのだから。