[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bep] learning lisp: recursive
- To: bep@argv.org
- Subject: Re: [bep] learning lisp: recursive
- From: TAKAHASHI Naoto <ntakahas@m17n.org>
- Date: Mon, 11 Jun 2001 10:14:07 +0900 (JST)
- Delivered-To: mailing list bep@argv.org
- Mailing-List: contact bep-help@argv.org; run by ezmlm
- User-Agent: SEMI/1.14.3 (Ushinoya) FLIM/1.14.2 (Yagi-Nishiguchi) APEL/10.2 Emacs/21.0.104 (sparc-sun-solaris2.8) MULE/5.0 (SAKAKI)
Reiko TAKAHASHI (高橋玲子)writes:
> } アルファベットが入っていませんが、2* というシンボルが関数名です。
> 数字以外のなにかが一つでも入っていれば、その記号(というか記号列という
> か……)はシンボルになれるんですね?
残念ながら数字以外にもシンボルとして使えないものはあります。括弧とかセ
ミコロンなんかがそうです。まあ特殊な技を使えばそれらも大丈夫なんですが、
説明はやめておきます。
自分でシンボルを作るときは、一文字目をアルファベットにしておくのが無難
です。また2番目以降の文字としても、特別な理由がない限りアルファベット
と数字とハイフンだけにしておくのが普通です。それから Emacs Lisp ではア
ルファベットの大文字と小文字を区別しますが、普通シンボルとしては小文字
だけを使う習慣です。
> (1- n)と書いた場合、最初の 1- は関数で、つぎの n が引数だったんですね。
そうです。
> 「再帰的呼び出し」が解ったかどうか、確認のために、もう一度だけ……、
> (defun fact (n)
> (if (= n 1)
> 1
> (* n (fact (- n 1)))))
> nが4、(fact 4) の場合、
> (* 4 (fact (- 4 1)))
> ↓
> (* 4 (* 3 (fact (- 3 1))))
> ↓
> (* 4 (* 3 (* 2 (fact (- 2 1)))))
> ↓
> (* 4 (* 3 (* 2 1))) => 24
> ですね。
すばらしい。模範的な解答です。
> すごいとんちんかんかもしれませんが、Lispには、-の付く数(負の数)はあり
> ますか? たとえば、
もちろんあります。書き方も普通どおり -4 のように書きます。
> (fact -4)
> とかの場合(があったとしたら)、
> (* -4 (fact (- -4 1)))
> ↓
> (* -4 (* -5 (fact (- -5 1))))
> ↓
> (* -4 (* -5 (* -6 (fact (- -6 1)))))
> とかになって、永久に終わらない気がするのですが……。
するどい。おっしゃる通りです。上の fact の定義だと、負の数が引数として
渡された場合に止まらなくなります。また、1.5 などの小数が与えられた場合
も止まりませんね。最初に「小さめの正の整数を引数に与えて下さい」と書い
たのはそういう理由だったんです。
実は一番最初はちゃんと引数の値をチェックするような関数を書いたんですが、
そうすると肝腎の「再帰」の説明をする前にそっちを説明する必要が生じてし
まい、その結果焦点がぼけてしまいそうだったのであえて簡単な定義にしまし
た。
再帰的な定義をするときは、このように無限ループに落ち入らないよう常に気
を付けなければいけません。それにしてもよく気が付きましたね。プログラマ
の素質があるんじゃなでしょうか。
> それと、(if ...) というのもLispでは「関数」と考えられますか?
はい。厳密には special form になりますが、「ちょっと変な関数」と考えて
いただいて結構です。別スレッドで井上さんの説明がありましたが、書き方は
(if 条件式 S式その1 S式その2 S式その3 …)
となります。もし「条件式」を評価した結果が nil 以外になれば、
「S式その1」を評価し、その結果を返します。またもし「条件式」を評価した
結果が nil になれば、「S式その2」「S式その3」…を順番に評価し、一番最
後のS式の結果を if の結果として返します。
また「S式その2」以降は省略できます。この場合の形は
(if 条件式 S式その1)
となります。「条件式」を評価した結果が nil 以外なら上と同じで、「条件
式」を評価した結果が nil ならば if の返す値も nil になります。
ちょっと面白しいのは、条件式を評価した結果が「nil 以外なら」何でも「真
(しん)」とみなす、という点です。t に限らず、1 でも "abc" でも -273.16
でも「真」です。ですから、(if 1 2 3) を評価すると 2 になります。わかり
ますか?
> (= ...) と、(equal ...) は同じ意味で、評価した結果は数字ではなく、 t か
> nil になる、と考えていいですか?
同じ意味ではありませんが、おっしゃるとおり評価した結果はどちらも t か
nil になります。
= は数値同士しか比較できません。ですから (= 'a 'a) はエラーになります。
equal は何でも比較できます。(equal 'a 'a) は t になりますし、
(equal 'a 1) は nil になります。じゃあ equal だけあればいいじゃないか
と思われるかもしれませんが、= にもいいところはあります。
まず第一には、数値の比較に特化されている分だけ実行が速いということです。
また、引数に数値以外が来たときにエラーになるということは、自分で書いた
プログラムの間違い探し(デバッグ)に役立ちます。さらに他人が書いたプログ
ラムを読む場合でも、ああここの変数はどっちも数値なんだな、ということが
はっきりします。
二つの「もの」が同じかどうか判定する関数は他にもいろいろあるのですが、
まあそれはおいおい出てくるでしょう。
> # 「頭山」のあらすじ(?)が、
> http://member.nifty.ne.jp/~tomikura/j/rakugo/a/atamayama.html
> にありました。しかし……、なんて体の柔らかい人なんだ……!!
北欧神話(エッダ)には、主神のオーディンが自分を自分に捧げものとして与え
るという場面が出てきます。私は高校生のときにこれを読んで、「おお、リカー
シブ」と思ったもんです。かわいげのない高校生ですね。(笑)
--
TAKAHASHI Naoto
ntakahas@...
http://www.m17n.org/ntakahas/