• ベストアンサー

Lispの問題

lispを最近習い始めた初心者です。以下の問題【2】つが解けないので回答をお願いします。 【1】 ;;; CONS CL-USER(1): (cons 'a 'b) (A . B) ; ドッティドペア ;;; (1 2 3) ;;; (1 . 2) 関数 CONS は上に並べたある関数の特別な場合と同じと見ることができる それは何か? 以下の ◇ は何に相当するか? ;;; (cons a b) ≡ (◇ a b) 【2】関数 PRINC を利用し、リストをドッティドペアとしてプリントする関数を定義してみよ です。【2】の問題は (dotted-print '(1 2 3)) => (1 . (2 . (3 . NIL))) が例としてあるのですが、理解できません。 例についても解説していただけると助かります。 【1】,【2】単体の回答でもどうかご教授御願いします。 後lisp初心者にオススメなサイトなどあったら教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

#1>(1 . (2 . (3 . NIL))) => (dotted-print '(1 2 3)) >とこういう形にしろという問題なんですよね? 全然違います。 リストをドッティドペアとしてプリントする関数を作れという意味で、 dotted-print は、その定義されるであろう関数です。 >(dotted-print '(1 2 3)) => (1 . (2 . (3 . NIL))) は、 dotted-print にクォートされた(1 2 3) というリストを渡すと、 それを (1 . (2 . (3 . NIL))) のような ドットペア表現で出力しますという例です。 #1のプログラムを入力してから (dotted-print '(1 2 3)) のように実行すると (1 . (2 . (3 . NIL))) のように表示されるはずです。 >プログラムの説明 既に、#2でも説明されているし、多分テキストでも説明されていると思いますが、 コンス ( a . b ) は、LISP で基本的な構造です。 x が ( a . b ) の時 (car x) は、 a を取り出し (cdr x) は、 b を取り出します。 プログラムでは、引数として渡されたリストを関数内の一時変数に、car と cdr を取り出し consp (consp は、引数がコンスであるかどうかをテストする述語です)でテストし、コンスであるなら、更にdotted-print を呼び出し処理させた結果を表示しコンスでない(アトム)なら、それを表示するという処理をしています。

chattesnoires
質問者

お礼

問題の意味も理解できてなかったんですね僕は; 大変わかりやすく説明して頂いたおかげで プログラムの意味も理解できました。 有難う御座います。

その他の回答 (2)

  • hpsk
  • ベストアンサー率40% (48/119)
回答No.2

【1】「上に並べたある関数」が何なのかわかりませんが,おそらくlist* でしょう. (list* が特に引数を2つとるときは,consと同じ働きをする) 【2】No.1の方のでいいと思います. > 例についても解説していただけると助かります。 たぶん,その問題が載っている本に書いてあると思いますが,Lisp(S式)の構文の定義に忠実に基づいてリストを表現すると. (1 . (2 . (3 . NIL))) になるのですが,これだと欝陶しいので (1 2 3) と書いてもよいことにしているのです.両者は書き方が違うだけで,全く同じ意味です. CL-USER(1): '(1 . (2 . (3 . NIL))) の出力結果を見てみれば実感できるかと思います. > 後lisp初心者にオススメなサイト Common Lispを一から本格的に学べるような日本語のWebページはあまりお目にかからないです. (http://user.ecc.u-tokyo.ac.jp/~t50473/onlispjhtml/ などはかなり有用ですが,中級者以上向けです) 書籍なら,Paul Graham,ANSI Common Lisp スタンダードテキスト(参考URL)をおすすめします.

参考URL:
http://www.amazon.co.jp/exec/obidos/ASIN/4894714337/249-9620681-4278719
chattesnoires
質問者

お礼

回答有難う御座います。 >(list* が特に引数を2つとるときは,consと同じ働きをする) list*で実行した所同じ結果がでました。 例などの説明も助かりました。 lispについて調べると英語のサイトばかりなんですよね。 URL参考になります。本もやっぱり英語のばかりで何か良いのないか探していたところだったのでおすすめの書籍見てみます。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

【1】 「上に並べたある関数」とは、どんな関数がならんでいたんでしょうか? 【2】関数 PRINC を利用し、リストをドッティドペアとしてプリントする関数を定義してみよ (defun dotted-print ( x ) (let ((a (car x))(b (cdr x))) (princ "( " ) (if (consp a) (dooted-print a) (princ a) ) (princ " . " ) (if (consp b) (dotted-print b) (princ b) ) (princ ")" ) )) とか

chattesnoires
質問者

お礼

回答有難う御座います。 【2】の問題ですが、これは (dotted-print '(1 2 3)) => (1 . (2 . (3 . NIL))) を (1 . (2 . (3 . NIL))) => (dotted-print '(1 2 3)) とこういう形にしろという問題なんですよね? よかったらプログラムの説明もお聞きしたいです・・・。

関連するQ&A

  • Emacs Lisp: consセルと引用符?

    お世話になります。 Emacs Lispについて勉強しています 今は、リスト、consセルについて勉強しています。 以下、拙い質問になるかと思いますが、よろしくお願いします。 Lisp Interactionモードのバッファに、 '(1 2 3) というリストを書いて行末でC-jを押下すると (1 2 3) という式を返します。 しかし、 (1 2 3) という式を書いて行末でC-jを押下すると Debugger entered--Lisp error: (invalid-function 1) というエラーになります。 これは、1が関数、2と3が引数として評価されるからですね。 さて、リストではなく「consセル」を作るとします。 (1 . 2) と書いてC-jを押下すると、やはり Debugger entered--Lisp error: (invalid-function 1) というエラーになります。 '(1 . 2) であれば (1 . 2) と、正しくconsセルが出来ます。 '(1 . nil) であれば (1) というリストを返します。 これは、cdr部がnilであるconsセルはリストになるからですね。 では、3と、「1とnilからなるリスト」のconsセルを作って、結果的に(3 1)というリストにしようとします。 '(3 . '(1 . nil)) この場合は、予想に反して (3 quote (1)) となります。 '(3 . (1 . nil)) であれば、 (3 1) となります。一方、 (3 . (1 . nil)) とすると、 Debugger entered--Lisp error: (invalid-function 3) となります。 まとめると、 3と、「1とnilからなるリスト」のconsセルを作って、結果的に(3 1)というリストにしようとした場合は、 '(3 . (1 . nil)) のように外側のconsセルはクォートし、内側のconsセルはクォートしない、ということになりますね。 このクォートの振る舞いの違いはなぜでしょうか。 よろしくお願いします。

  • リストを逆順にする関数(LISP)

    「初めての人のためのLISP[増補改訂版]」のP150のリストを逆順に関数がよくわかりません。 以下がその関数です。 (defun nreverse (x) (nrev2 x nil)) (defun nrev2 (x r) (cond ((null x) r) (t (nrev2 (cdr x) x) (rplacd x r) ))) xがnilになるまで再帰を繰り返し、((null x) r) で再帰を戻りますがなぜs (rplacd x r)でリストが逆順になるんでしょうか。例えばxを(a b c)とすると x:(a b c) r:nil ↓ x:(b c) r:(a b c) ↓ x:(c) r:(b c) ↓ x:nil r:(c) ↓ rplacd (c) (b c) ↓ rplacd (b c) (a b c) ↓ rplacd (a b c) nil となるのですが、これじゃあ全然リストは逆順になりませんよね。 誰が教えてください、お願いします。 ちなみにrplacd は第一引数のcdrを第二引数に変換する関数です。

  • lispでの文字読み込み

    lispでの文字読み込み 以下のようなテキストをcommon lispで読み込んでいます。 --a.txt-- あああ いいい ううう ええええ --------- このような感じで。 (let (in str) (with-open-file (in "a.txt" :direction :input) (setf str (read-as-string in nil)) ) ) このときに、いいいの下の空行を読み込むにはどうしたらよいでしょうか? 読み込むというか、空行があることが検出できればいいんですが。

  • 「初めての人のためのLISP[増補改訂版]」で

    「初めての人のためのLISP[増補改訂版]」のP.46の練習問題をやっていくと (setq A nil) nil (setq B '(87 58 90)) (87 58 90) (setq C '(I B M)) (I B M) (null t) nil (null A) t (null (null A)) nil (cadr B) 58 (+ (car B) (caddr B)) 177 (cadr C) B (set (car C) (cdr B)) (58 90) (car C) I (atom C) nil となりますが、 なぜ (atom C) でnilが返ってくるのですか? "C"はアトムではないのですか?

  • format関数が使えません(Lisp)

    Emacs23でformat関数を評価してもエラーが出て使うことができません。*scratch*で評価してもloadしても同じです。 例えば (format t "ddd") で Debugger entered--Lisp error: (wrong-type-argument stringp t) format(t "ddd") eval((format t "ddd")) eval-last-sexp-1(t) eval-last-sexp(t) eval-print-last-sexp() call-interactively(eval-print-last-sexp nil nil) このようなエラーが出て実行できません。 一体どうしてwrong-type-augumentとでるのかさっぱりわかりません。どなたか知恵を貸してください。

  • Elispで文字列がある文字列を含むかどうか判定

    Emacs lispで、ある文字列Aと文字列BがあってBがAを含むときにt, そうでないときにnilを返す関数はどのように書けますか?

  • lispについて質問です

    assoc関数と同じ動作をする関数(ただし、文字列も扱えるようにする)を作成したいと考えています 具体的には、 (setq S '(("1" "a")("2" "b"))) とあったときに、自作した関数(assoc_mojiとします) (assoc_moji "1" S) と実行したら ("1" "a") となるような関数です また、無い場合はnilを返します 条件分岐で関数を組み込み、成功した場合は結果を返し そのほかの場合はnilを返すというところまではわかりますが、 その条件分岐で定義する式が全くわかりません。 memberや、equalを使って、リストに含まれていれば、または指定した文字列が一緒ならば、返すなどしましたがまったくうまくいきませんでした。 どなたか、こういう関数を使ってこういう処理をさせればよいという風なヒントだけでもいいので、ご教授お願いします

  • emacsでcmmon lispのプログラムを作成します。

    emacsでcmmon lispのプログラムを作成します。 my-equal(A, B)= if A is an atom then if B is an atom then (eq A B) else if B is an atom then nil else if (car A)=(car B) then (cdr A)=(cdr B) else nil というのです。自分が考えたのは、 defun my-equal(x, y)= (cond ((atom x) (atom y)) (eq x, y) (atom) (t, nil) ((car x)=(car y) (cdr x)=(cdr y)) (nil)) というのでよろしいのでしょうか? また、4行目(この全文の)の意味がいまいち分かりません。

  • Lisp の問題がわかりません

    次の問題のプログラムを教えてください。 《多項式のかけ算》 1つの変数を含む線形多項式のかけ算を行なう関数 poly-times を定義する. 多項式は例えば 2x^4 - x^3 + x^2 + x-1 → (+ (* 2 X X X X) (* -1 X X X) (* X X) X -1) 2x4 - x3 + x2 + x-1 → (+ (* 2 X X X X) (* -1 X X X) (* X X) X -1) のように LISP の式で表現するものとする. すなわち, 第1要素が " +", 第2要素以降が項であるようなリストである. 演算子は +, * のみとし, -, / は使わない. 変数には X というシンボルを用いる. 項は, 整数, シンボル X, あるいは, 第1要素が "*" であるリストのいずれかであり, リストの場合, 第2要素に整数が入り第3要素以降は X, あるいは, 第2要素以降が X であるものとする. (実行例) >(poly-times '(+ X 2) '(+ X -2)) (+ (* X X) -4) >(poly-times '(+ (* 2 X X) X 5) '(+ (* X X) (* -5 X) 3)) (+ (* 2 X X X X) (* -9 X X X) (* 6 X X) (* -22 X) 15) 各項をかけ合わせてそれらの和をとればよいので, 2つの項をかける関数とか, 多項式と項を足す関数などを作って組み合わせれば できそうです. たとえば, (defun poly-times (x y &aux z) (dotimes (i (length (cdr x))) (dotimes (j (length (cdr y))) (setf z (embed-term (term-times (nth i (cdr x)) (nth j (cdr y))) z)))) (cons '+ z)) などと定義しておいて, 項同士のかけ算を実行する関数 term-times と, 1つの項を多項式に加える関数 embed-term をうまく定義してやれば 完成です. 自分でも試してみましたが、場合分けなどが多く、解けませんでした。 わかる方の御協力をお願いいたします。

  • Lispについてわからないことが(Scheme)

    あるLispの勉強ソフトで、 「関数lを『引数としてxを受け取ると、xの要素の数を返す関数』として定義しなさい。」 という問題があるのですが、私は以下のようにしました。 (define l (lambda (x) (if (= x null?) 0 (+ 1 (l (cdr x)))))) しかしこれだとオーバーフローと表示されて強制終了されてしまいました。 そこで答えをネットで検索したところ以下のものが見つかりました。 (define l (lambda (x) (cond ((null? x) 0) (else (+ 1 (l (cdr x))))))) これが正解なようですが、この2つのリストの違いがわかりません。 初歩的なことですがifの使い方を間違っているんでしょうか?

専門家に質問してみよう