[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bep] learning lisp: if, and, cond
- To: bep@argv.org
- Subject: Re: [bep] learning lisp: if, and, cond
- From: Reiko TAKAHASHI <HFC03614@nifty.ne.jp> (高橋玲子)
- Date: Wed, 20 Jun 2001 07:35:48 +0900
- Delivered-To: mailing list bep@argv.org
- Mailing-List: contact bep-help@argv.org; run by ezmlm
r高橋です。
Reply TAKAHASHI Naoto <ntakahas@...>'s message:
} はい、いいようですね。もしかして初 defun ですか?
} だとすると、これで今日から lisp プログラマですね。
きゃっ、かっこいい……! なんだか、とーっても似合わない感じだけれど、
うれしいです(^_^)。
} > (if ...)の中身について、条件式を評価した結果が t の場合どうするかのS式さ
} > えあれば、nil の分のS式はべつになくてもいいんだ、ということが、教えていた
} > だいていたはずなのに初め思いつけず、「うわっ、nil の分はどうしよう……」
} > と最初少し悩みました。
}
} 上の書き方でいいんですが、もし明示的に nil を返したいのなら、そのまま
} nil と書けばいいんですよ。もちろん nil もS式です。たとえば
}
} (defun meaningless (arg) nil)
}
} とすると、何を引数に与えても nil を返す無意味関数 meaningless が定義で
} きます。
実は私、最初にあのfactを書いたときには、悩んだあげく、最後に nil を付け
ていました。でも、なんかそれってずるい気がして(^_^;)、「きっと、ほんとう
はこんなわざとらしいことをしなくたって、結果が nil になるようにできるんだ
ろうな……」と思いながらいただいた過去メールを読み直していたら、「条件式
のあとに一つしかS式がなくて、条件式を評価した結果が nil だったら if 全体
の結果も nil になる」みたいなお話を見つけたので、「おお! これじゃ!」と
喜び勇んで nil を消したんです(^.^)。
でも、nil は書いておいたほうがいいんですね。たしかに、よくよく考えてみる
と、あとから読んだとき、nil があったほうがわかりやすい気がします。
} もし仮にR高橋版 fact を、明示的に nil 返すように書き変えるなら、
}
} (defun fact(n)
} (if (and (integerp n) (>= n 1))
} (if (= n 1)
} 1
} (* n (fact (- n 1))))
} nil))
}
} ですね。
はい、わかりました。
ところで、Lispを書くときの字下げ?(indentation)には、なにか決まりのよう
なものはありますか?
} さて、実はここの and の中の integerp と >= の順序は非常に重要です。も
} し >= を先にして (and (>= n 1) (integerp n)) としてしまうと、(fact 'x)
} とか (fact "abc") とかやったときエラーになってしまいます。>= の引数は
} どちらも数値でなければならないからです。
あっ、これは考えませんでした。
たしかに、integerp と >= をC-h fすると、
(integerp OBJECT)
(>= NUM1 NUM2)
ってなっていますね。読んでいたのだけれど、全然気づきませんでした。
>= のヘルプの中に、
Both must be numbers or markers.
と書かれているのですが、"markers"ってなんですか?
} and の一般形は (and 条件1 条件2 条件3 ...) という形をしていますが、
} 条件1, 条件2, ... を全部評価してからそれらが全部真かどうか調べるのでは
} ありません。条件xを前から順番に評価して行き、どれか1つが nil となった
} 時点で残りの条件は無視して即座に nil を返します。ですから、
}
} (setq x 5)
} (and nil (setq x 6))
}
} とした後でxの値を調べても5のままになっています。
はい、これはわかりました。↑の nil もずるい感じの nil ですね(^_^)。
} Emacs Lisp が扱える整数の範囲には限りがあり、それを超えると変になりま
} す。この範囲はプログラミング言語としては狭い方ですが、もっと大きな数が
} 使いたいようになる頃には、どうすればいいかもわかってくると思います。
あっ、そうなんですね。電卓みたい。
} cond の一般形は次のような形をしています。
}
} (cond
} (条件1 S式1の1 S式1の2 S式1の3 ...)
} (条件2 S式2の1 S式2の2 S式2の3 ...)
} (条件3 S式3の1 S式3の2 S式3の3 ...)
} ...
} )
}
} 「条件x」を上から順に見て行き、評価結果が真になったら
} 「S式xの1」「S式xの2」「S式xの3」…を順番に評価して最後の「S式xの?」
} の値を返します。
} and の場合と同様、残りの「条件x+1」「条件x+2」…は調べさえしません。
これは便利そうですね!
} では cond を使って fact を書き直してみましょう。
}
} (defun fact (n)
} (cond
} ((not (integerp n)) nil)
} ((< n 1) nil)
} ((= n 1) 1)
} (t (* n (fact (1- n))))))
}
} なんとなく想像つきますか?
……初めに読んだとき、最後の t がわかりませんでした。
(not ...) というのもあるんですね。
} 最後の「条件4」の t がちょっとわかりにくいかもしれません。上で書いたよ
} うに、cond は条件xが真になったところでそれ以降の条件のチェックをとばし
} ます。ということは、もし「条件4」のところまで来たのならば、
}
} ・nは整数でなくなく(つまり整数)、
} ・かつ1より小さくなく(つまり1以上)、
} ・しかも1でない、
}
} ということになります。わかりやすく言うと、nは1よりも大きい整数だという
} ことになります。nが1よりも大きな整数であれば、そのときの答はnの値にか
} かわらず (* n (fact (1- n))) です。ですから「条件4」を t (つまり真)
} としておいて、常に (* n (fact (1- n))) を返すようにしているわけです。
これも、「ずるい」tっぽい? もう絶対に t だとわかっているので、なんと
条件式のところに、最初から t を入れてしまう、ということですよね。
} cond を書くときは以上のように、まず例外的な場合を取り出し、最後に「そ
} れ以外なら」という意味で t という条件を置くのが普通です。もちろん Lisp
} は nil 以外をすべて真ととらえますから、t の変わりに 1 とか 'a とか
} "hello" とか書いてもいいんですが、わかりやすさのため t を使うのが習慣
} です。
}
} なお、cond の条件の最後が t でなく、かつすべての条件が nil となった場
} 合、cond 自身の値も nil となります。
「cond の条件の最後が t でなく」というのは、「nil だったら」という意味
ですか?
nil 以外は全部「真」とみなされる……んですよね??
**-***-***-***-***-***-***-***-***-***-***-***-**
Reiko TAKAHASHI (高橋玲子)
E-mail: HFC03614@...
ICQ UIN: 85924121 (Twinkle)
**-***-***-***-***-***-***-***-***-***-***-***-**