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になっても、必ず「判断式」に値が渡されて、判断は「判断式」の値に基づいて行われるのだから。