2010/05/19

t, nil, '(), #t, #f

メモっておきたかったので、勝手にまとめました。「誰でも編集可」です。

私の日本語がカオスですいませんでした・・・。

「scheme も Common Lisp みたいに、nil が偽で空リストも偽で空リストが nil 、だと良いのになー。」「(car nil) や (car '()) が nil なのも良いなー。」と思ったのでした。なんで Scheme はそうじゃないんだろう?というのが切欠です。




Chaton の方からも転載・・・。
shiro
#
@valvallow @finalfusion 括弧のざわめきに混じって俺を呼ぶ声が聞こえた、ような気がした。
#
nil問題はいくつかの要素が絡んでいるので、分けて考えると良いかと思う。
#
とりあえず返しておける値があると便利、という話と、それがリストのゼロ元である()であると便利、という話。
#
とりあえず返しておける値、というのは、例えばwhenの条件不成立時とか、findで値が見つからなかった時とか、そういう何かの不成立を示すユニバーサルな値ってこと。
#
値そのものは何でも良いんだけど、条件判断と組み合わせた時に偽と判断されるようになってると色々便利。
#
ちょっと一休み
2010/05/19 02:23:04 PDTshiro
#
一方で、主要なデータ型のゼロ元が偽になるようになっていると便利、ということがある。再帰/繰り返ししていってゼロ元に出会ったら終わり、という処理が短く書けることが多いから。
#
リストが主要なデータ型であれば、空リストが偽であると便利。
#
整数が主要なデータ型であれば、0が偽であると便利 (C言語とかね)。
#
中には、リストのゼロ元も整数のゼロ元も文字列のゼロ元も偽にしちゃおうって言語もある (Perlとか)。
#
ただ、この二つの要素、どちらもトレードオフがある。
#
不成立/不存在を示す値=偽値、という設計だと、「偽値が見つかった」という答えを返すのがちょっと困る。gethashでnilが返って来た時、値は存在しなかったのか、それともnilという値だったのか。
#
CLでは多値を使ったりしてこの問題を回避するけど、アドホックな感じは否めない。厳密にやるなら、「どんな値とも一致しない値」を使って不存在を示すしかなくて、そうすると例えばHaskellのMaybeみたいに値を一段ラップしてやることになる。
#
ゼロ元=偽、という設計についても、そのデータ型にとっては便利になるんだけど、他のデータ型にとっては便利にならないっていう非一貫性がある。CLで()が偽で便利なのは、リストばっかり使うからそう思ってるだけ。Cで書いてて0が偽で便利なのは、整数のドメインで作業することが多いから (あと、不存在を示すヌルポインタってものもあるけど)。
#
つまり、「便利」という時には、「その機能が便利になるようなコードの書き方をしているから便利なのだ」ということになってる可能性がある。
2010/05/19 02:37:09 PDTshiro
#
Schemeは前者 (不存在を示す値) については不徹底で、findで#fが返ってくる問題とかあるんだけど、後者についてはいろんなデータ型に対して中立ってことなんじゃないかと思う。
#
結局、()と#fが区別されたらそれに依存したコードを書けて、それもまた「便利」ではあるので、どういうモデルで世界を見てるかってことなんだよね。
#
あと、シンボルのnilとtを特別扱いすることに対しては私は多いに不満。プログラマから使える単語を取り上げる言語は嫌い。
2010/05/19 02:42:54 PDTvalvallow@twitter
#
すごくよくわかりました!ありがとうございました m(_ _)m
2010/05/19 02:49:49 PDTshiro
#
CLで書いてる時は確かに()=nil=偽にばりばり依存したコードを書いてるけど。たまに「シンボルかリストかで分岐したい」なんてコードを書きそうになってnilのせいできーってなることはある。
2010/05/19 03:42:36 PDT齊藤
#
そういや R6RS が出来る前に未定義値は「未定義であることを表す (比較可能な) オブジェクト」にしようみたいな話があったと思うんですが、結局は「何も期待するな」になったのは、やっぱ Scheme 的にそういう依存は好ましくないってことなんでしょうか。
2010/05/19 03:43:38 PDTshiro
#
ああ、そんな議論がありましたね。
#
私の印象では、依存が好ましくないというより、未定義値の使いどころ/位置づけがうまく決まらなかったからじゃないかなあという気がしています。「未定義値」という値として使えるってことになると、それを普通に引数に渡したり戻り値として返したり、とやることになるわけですが、それが出来て嬉しいの/何に使えるの? ってことです。
#
「使っちゃいけない値/当てに出来ない値」を示す値、というのは矛盾していて、値として存在してしまったら使えちゃうわけですから。
2010/05/19 03:51:59 PDT齊藤
#
意味が無いところは意味が無いままな方が自然ってことですね。

shiro さんありがとうございました。


そういえば、clojure は?



On LispプログラミングGauche

2010/05/18

On Lisp からいくつか

読んでいて「おっ」と思ったところを、メモっておいても良いですか?
関数定義内にあるマクロ呼び出しは関数がコンパイルされるときに展開形に置換される. マクロを呼び出す関数がコンパイルされた後にそのマクロを再定義したらどうなるだろうか? 元々のマクロ呼び出しの形跡は残っていないので,関数内の展開形は更新されない. 
applyやfuncallの第1引数としては渡せないし, 呼出側の関数が新たなローカルな束縛を生むような環境では使うべきでない.
マクロ呼び出しは,書かれた所に直接展開される.
マクロはマクロ呼び出し内の引数の評価を制御する. 評価回数は引数がマクロの展開コードのどこに置かれるかによるが, 1回でも複数回でも良いし,全く評価しないこともある.
Lispプログラムでのマクロ展開は全てプログラムがコンパイルされたときに行われ, コンパイル時に実行できるどのような計算も,実行時にプログラムを遅くすることはない.
関数は(例えばapplyに)引数として渡すことも,関数から返すことも, データ構造内に格納することもできる. マクロではそれらはどれも不可能だ. これらはマクロ呼び出しをλ式で包むことで実現できる場合がある.

言われてみれば、そりゃそうだ、というものが多い気もしますが、なるほどです。

LET OVER LAMBDA Edition 1.0 もおもしろいけど、On Lisp はもっとおもしろい。LET OVER LAMBDA Edition 1.0 の著者が以下のように言うのもわかる気がする。
マクロに興味を持つ者なら誰もが、On Lisp の一言一句を逃さず読まなければならない。


こんなに引用ばかりで良いのかな。でもメモっておきたかったので。

On LispLET OVER LAMBDA Edition 1.0

それでも Ctrl は CapsLock の位置にないと困る。

追記

レジストリ書き換えてるらしいです(笑)


この悩みを解消してくれるソフトは、意外なところにありました。これです。
Windows + Emacs(or Meadow)な人であれば、一度はこのソフトのお世話になり「オレ強ぇー!」になることだと思います。不幸の始まりですね(後述)。


まず

ここは人それぞれでしょうが、Emacs キーバインドが必要なければ無効にします。


次に

タスクトレイからキーボードレイアウトを選びます。(画像はポイントがズレて「オプション」のところになってますが)


後は

お好きなようにキーを配置。D&D で指定できます。



最後に

再起動で完了。


または

こういった方法もあるようです。

@valvallow Emacs 内だけでよければ keyboard-translate でなんとかなると思います。 Windows なら Emacs の外で Ctrl なんてそんなに使わないでしょう。less than a minute ago via web


後述するほどのことでもありませんが・・・

Emacs のキーバインドは慣れるまでにしばらくかかります。しばらくかかりますが、慣れてしまうと「もう全部 Emacs キーバインドがいいんだぜ!」となることもしばしばあります。Windows を使っている人であれば、Visual Studio も秀丸も Terapad もブラウザもオフィスもファイラーもあれもこれもオレもお前も君もあなたも、とやっているうちに  XKeymacs に辿りつくわけです。

このソフト、すごく強力で、アプリケーションごとの個別カスタマイズもできちゃうんですね。アプリケーション組み込みのショートカットと Emacs キーバインドの相性が悪ければ、個別にカスタマイズできるわけです。すごくハッピーですね。

ですが、個別にカスタマイズできるお陰で泥沼化していきます。カスタマイズ疲れ、とでも言いましょうか。。最終的に「Emacs キーバインドは Emacs だけでいいや。。」となること請け合いです。

追記

レジストリ書き換えてるらしいです(笑)

入門 GNU Emacs 第3版入門Meadow/Emacs

2010/05/15

defmacro while

do マクロの使い方を覚えられないクラスタです。
再帰で書いてみましたが、do マクロ版と同等かよくわかりません。

上が、On Lisp に載ってる版。下が再帰版。

追記

最基盤再帰版は戻り値が常に nil ですね(笑)

追記2

格好悪いですが、これなら?

追記3

nil で良かった件。

追記4

prog1 の方もちゃんと戻ってないですね(笑)

追記5


@valvallow 暗黙の block と tagbody が無いので、return や return-from や go が使えない点がホンモノと違うかも?less than a minute ago via Tween



追記6




On Lisp

2010/05/14

pluggable Y Combinator 2

さっきの続き。
コードは以下のとおり。

おもしろいな~。

追記

;(compose hoge (compose fuga ... は (compose hoge fuga ... で良かった。

(time ((Y (compose (make-memoize)(make-trace) fib)) 10))
;(time ((Y (compose (make-memoize) (make-trace) fib)) 10))
; real 0.000
; user 0.000
; sys 0.000
; call with : 10
; call with : 9
; call with : 8
; call with : 7
; call with : 6
; call with : 5
; call with : 4
; call with : 3
; call with : 2
; call with : 1
; call with : 0
89

プログラミングGauche

pluggable Y Combinator

pluggable と付いてますが、メモ化された Y Combinator と違って、ただの素の Y Combinator です。
どちらかというと、メモ化関数を Y Combinator に対応させるということで良いと思います。コードはこちら。

参考にしたのは、昨日に引き続きこちら。これすごくおもしろいです。やばいです。

2010/05/13

メモ化された Y Combinator

メモ化は The Seasoned Schemer にも出てきますね。Y Combinator は昨日のコレを改造しました。


すげー。これカッチョイイな!!memoized-Y 。

こちらを参考にしました。こんな使い方があったとは・・・。
私も以前 JS で Y してるコードがありましたので、うp。

ほんと、「マクロのない Sceme」といったノリだなーなどと。

追記

少し修正したので。


On LispThe Seasoned Schemer

On Lisp memoize



追記


メモ化されてNEEEEEEEEEEE!ということで。

でも、これでもメモられたのは35だけか・・・。うーん。

On Lisp

repeated


計算機プログラムの構造と解釈