Gauche > Archives > 2010/10/26

2010/10/26 06:54:27 UTCshiro
#
またnilと#fが話題になっているようだが、whenの「戻り値」の扱いについて。CLではwhenは条件不成立時にnilになるのでそれを利用した書き方ができるが、Schemeではwhenの戻り値はundefinedなのでそうはいかない。
#
Schemeではむしろ、when(やunless)は「副作用目的」を明示していると考えると良い。戻り値は使えないよ、という記号。
#
SchemeでCLのwhen的に、戻り値を使いたい場合は、(and <条件> <処理>) と書く。これなら値に意味があることがわかる。
#
欠点として、(when <条件> <副作用> <式>) の場合は (and <条件> (begin <副作用> <式>)) としなければならない。これもbeginによるsequencingが副作用の目印だと考えることはできる。
#
Clojureでdoが副作用のしるしになるのと似た感じ。
2010/10/26 06:57:22 UTC(び)
#
うん。慣れのせいかもしれないけど、私もその方が自然に思える。
#
そうだひとつ思い出した
#
gosh> `(,(values))
(#<undef>)
#
これってどうなんだろうなー、と思ったんですよね。
#
gosh> `(,@(values))
gosh>
#
これとか
2010/10/26 07:01:07 UTCshiro
#
それは敢えて#<undef>にしてるわけじゃなくて ,(values) って式自体がもともと不正なんで何が出てきても不思議は無い(たまたま#<undef>だった)ってことなんだけど、誤解のもとかなあ。
2010/10/26 07:01:16 UTC(び)
#
値を返さない、のと未定義値を返す、の違いがちょっとまだわからない
2010/10/26 07:01:19 UTCshiro
#
例えばこんなことも起きる
#
gosh> `(,(sqrt 2) ,(values))
(1.4142135623730951 1.4142135623730951)
2010/10/26 07:01:41 UTC(び)
#
ぅぉ
#
あれ、(values)って不正なんですか?
2010/10/26 07:02:43 UTCshiro
#
(values)は0個の値が許されてるところに使うのはOK。(unquote <式>) では<式>はひとつの値を返さないとならない。したがって ,(values) つまり (unquote (values)) は不正。
2010/10/26 07:03:15 UTC(び)
#
ああなるほど
#
それはそうですね
2010/10/26 07:03:45 UTCshiro
#
Gaucheでは(values)は戻り値が無いので、戻り値レジスタに変化がない。その直後に戻り値を無理やり読み出そうとしたら、その前にあった戻り値が見える。Cでauto変数を初期化せずに読んでるのと一緒。
2010/10/26 07:05:32 UTC(び)
#
なるほど
2010/10/26 07:06:53 UTCshiro
#
まあ、言語としては値の数の不整合が起きたところで例外あげた方が親切だしわかりやすくはあるよね。チェックするぶんだけ重くなるけど。そのへん、GaucheはC言語的文化を引きずってるかも (自分の足を撃ちたきゃ撃てる、って意味で)
2010/10/26 07:07:27 UTC(び)
#
その文化には異論はないです。
2010/10/26 07:09:19 UTCshiro
#
でも試してみて#<undef>が帰ってきたら、ああ#<undef>が帰ってくるものなんだなあ、って思っちゃうよねえ。
#
複数式が、というより「戻り値が当てにできない」ってとこ>副作用の印 RT: @nitro_idiot: でも複数式を書けるブロック(whenとか)が全部副作用のための印だって言うならlambdaも副作用の印に見えるよね
#
そういう意味ではbeginはちょっと例がまずかったか。あと、そのような理由から教育に使う時はlambdaの中の式はひとつに制限すべし、ということを言う人もいる (複数式並べたかったら陽にbeginつかえ、と)
2010/10/26 07:17:46 UTCshiro
#
読者が極めて限られるような RT: @golden_lucky: Schemeベストプラクティスという本で1章をまるまる#fと'()の話に割り当てたら、ベストセラーになるかな
2010/10/26 07:19:04 UTCnitro_idiot@twitter
#
なるほど。whenの使い方の問題ですね
2010/10/26 07:20:59 UTCshiro
#
@nitro_idiot whenとformatの話はわからなくもないけれど、ちょっと特殊な例という気もする。formatしたい値が式になってたら、一度letで受けなくちゃならなくて、
#
実際 (let ((var <式>)) (副作用 var) var) というのは非常によく出会うので、Gaucheでは (rlet1 var <式> (副作用 var)) と書けるようにしてしまった。
2010/10/26 07:21:56 UTC(び)
#
そういえば when/ や unless/ は and的な動作するようにしたのを今頃思い出した
2010/10/26 07:24:35 UTCshiro
#
まあ何が特殊かは人によるから、そこが言語設計の難しいとこだけど。
2010/10/26 08:39:40 UTCcut-sea
#
あったあった > when/ unless/
2010/10/26 08:54:55 UTCshiro
#
kahuaはモナド使いまくりだからわかりにくい面もあるよな。ドキュメントの出力って意味では副作用だけど、実際の出力は式の評価時よりも後で起きてるから、単純に戻り値との関係で判断できない。
2010/10/26 10:21:15 UTCcut-sea
#
ただテンプレート中での(DBから取得したレコードの)フィールドアクセスの作法が見えん
#
誤爆った
#
orz
2010/10/26 10:43:18 UTC(び)
#
今のkahua.elemの問題点は、とにかくデバッグが難しいこと。どれがエラーになってるのかわからない。
#
だから、本当はレンダリングの際、ソースコード上の位置情報をきちんと管理して、エラー発生時にそいつを出して上げる(普通のインタプリタやコンパイラがやっていること)必要がある。
2010/10/26 12:41:51 UTCshiro
#
モナドとしてライブラリ化できたりすると嬉しいかもしれないんだが、モナドパターンがSchemeで使いやすいとは限らないのがなあ…