lispのwhileとは?その特殊形式を解説

このQ&Aのポイント
  • lispの特殊形式whileを詳しく解説します。
  • whileの定義と使い方について説明します。
  • lispのwhileの動作や注意点についても紹介します。
回答を見る
  • ベストアンサー

lispのwhile

lispの特殊形式whileを以下のように定義します。 (while 判定条件 本体…) 第一引数である判定条件を評価し真ならば本体を評価しもういちど判定条件を評価、偽ならば本体を評価しない。 この時次のコードでよくわからない部分があります (defmacro image (var list &rest forms) `(let (($list$ ,list) ($r$ nil) (,var nil) ) (while ($list$ (nreverse $r$)) (setq ,var (pop $list$)) (push (progn ,@forms) r) ))) ($list$ (nreverse $r$)) この文は 偽(つまりnil) になりえるのですか? $list$はpopを繰り返すのでループを繰り返せばnilになるでしょう。 しかし (nreverse $r$) はpushを繰り返すのでnilにはなりえないと思います。 また、もしnilになりえたとしても (while (nil nil)) は (while (nil)) と同値なのでしょうか? ちなみにこれはlispの参考書のコードそのままです。 読み進めていくうちにだんだん難しくなってきました。 もうどれだけ考えてもわからないので、気持ち悪い思いはしながらもどんどん先に進んでいます。 こんな勉強法でいいんでしょうか? 不安になります。

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

  • ベストアンサー
回答No.3

あくまでも想像ですが、whileの正しい定義は (while (条件 最終結果) 本体 ...) では無いのでしょうか。 「条件」が真である限り、「本体」を評価する。 「条件」が偽になると、「最終結果」を評価して、その値を式全体の値とする。 といった動作かと思います。 そのように考えると、imageはあるリストを元に、 それを加工したリストを創りだすマクロとなります。 (image x '(1 2 3) (+ x 1)) ; => (2 3 4) マクロが難しいのであれば、マクロの展開型を表示してみるといいと思います。 詳しくは「lisp macroexpand」などで検索してください。

その他の回答 (3)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.4

#3の回答にもあるように、そもそもwhileの定義が違っています。 「初めての人のためのLisp 改訂増補版」をお使いと思いますが、その本での whileの定義はp110からp111にあります。 質問にあるプログラムで言うと、popを繰り返して空になったらそこでループを終了します。 このとき nreverse $r$ を実行して、その値が最終的な結果になります。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

もう 1つ質問: この「コード」はどのように使うのですか?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

その「コード」にはどのような意味があるのですか?

関連する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を第二引数に変換する関数です。

  • while文と無限ループの違い

    はじめまして。大学でC++を習い始めたばかりの初心者です。 最近while文とwhile文と使った無限ループを知ったのですが、 両者の違いがイマイチわかりません。 私のイメージですと、while文は条件が真である限り何度でも判定し 条件が偽になればループを抜ける。 一方無限ループもif文を使った条件が真にならない限りbreakしない。 while文の偽と判定する部分がif文で真と判定するだけで、同じような気がするのですが… ド素人の考えで恥ずかしいのですが、違いをわかりやすく教えてください。

  • perl while pushで条件が無かったら0

    恐れ入ります。perlで、 push@list,$1 while $body=~s!<div>(.*?)</div>!!; として(.*?)部分を抜き出して@listを作成していますが、 <div>(.*?)</div>が存在しない、つまり条件に合致しない場合は0を代入したいのですが、どのようにすればよいでしょうか。よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • unsigned int型と int型の型変換の上位性

    if(-10<1u)の条件判定はunsigned型で評価され偽となります。 int型 unsigned int型とも32ビットで考えたとき、 1u = 0x00000001 -10 = 0xfffffff6で10進法では4294967286になります。 条件判定をunsigned型で考えれば確かに-10<1uは偽になり int型で考えれば-10<1uは真になります。 「通常の算術変換」によれば、「一方のオペランドがunsigned int型をもつ時、他のオペランドをunsigned int型に型変換するとあります。」 よって、if(-10<1u)の条件判定はunsigned型で評価され偽となりますが、 「一方のオペランドがint型をもつ時、他のオペランドをint型に型変換する。」では何故いけないのでしょうか? 宜しく願います。

  • 明示的なオブジェクトの削除

    以下の様なコードを用いてthreadを走らせています。 my $cond = 0; while($cond == 0){  {   my $thread;   my @threads;   my $index = 0;   while ($index < @param1){    $thread = threads->new(\&func, $param1[$index++], $param2);    push @threads, $thread;   }     sleep(1);     while (@threads > 0){    $thread = pop @threads;    $thread->join();   }  }  condcheck(); } 条件が満たされるまで、一定の処理を行うthreadを複数走らせるというものなのですが、 これを実行すると、perlの使用しているメモリがどんどん増えて行っているのを確認しました。 #@threadsや$threadのスコープが外れるようにしているのになぜ? newしたthreadオブジェクトを、明示的に削除したいのですが、どのようにすればよいでしょうか?

    • ベストアンサー
    • Perl
  • xyzzyの実用サンプル

    LISPを覚えるために、xyzzyを使うことに決めました。 手始めに便利な機能が設定できれば励みになるかと思い、いきなり敷居が高いですが、次の内容がしたいのです。 F1を押すと、xyzzyの下の欄でurlを打つと、エディタ部にヘッダーを含めたHTMLテキストが表示される (defun poor-http (host file) (interactive) (let ((st (connect host 80)) form) (write (concat "GET " file " HTTP/1.0\r\n\r\n") :stream st) (terpri st) (while (setq form (read st nil '#1=:eof)) (when (eq form #1#) (return)) (insert form)))) (poor-http '203.216.243.218' "/index.htm" ) ctrl+jと実行すると、関数がありませんとなります。 途中で挫折しましたが、これらの機能を満たす gethttpsrc.lを作成する方法が知りたいです。 今のところの知識は nil t が真偽値で()でS式を作成する、まではわかりました。(あっているのだろうか?)

  • 紙谷氏の「Perl/CGI入門」、ハッシュeach関数の例題について

    ハッシュのeach関数を使って「猫はcat犬はdogお茶tea」と表示させるプログラムの主要部分です。 %list = ("猫"=>"cat" , "犬"=>"dog" , "お茶"=>"tea"); while( ($key,$val) = each( %list ) ){   print "$keyは$val"; } whileの条件部分の意味が分かりません。 ・なんで条件部分なのに代入みたいな式が入るのか? ・$keyと$valというのは普通のスカラー変数とは違うのか? 良く分からないので質問の仕方もおぼつかないですが、どなたか分かりやすく説明して頂けないでしょうか?

    • ベストアンサー
    • Perl
  • データベースからのarray を javascript に格納する方法

    行き詰っているので、力を貸してください。あるプロダクトの名前、ID、及び値段をデータベースからPERL DBIで引っ張ってきています。 <option value="id">$name</option>という形になっています。 同じページの同じフォームにたくさんあるオプションの中からある名前を選ぶと、値段をテキストボックスでonCheck で表示させたいのですが、データベースからとってきた配列はフォームの中のwhile文の中に入っているため、どうやって、<header>の間のjavascript の配列に入れることができるのでしょうか? スクリプトは下記の通りです。 PERL/DBI form名:mbscalcTb my $sql = "SELECT ProductId,.NameJ,.PSJ from Security"; my $sth = $dbh->prepare($sql); $sth->execute(); my $row; while ( $row = $sth->fetchrow_hashref() ) { my ( $ProductId, $NameJ, $psjtb ) = ( $row->{ProductId},$row->{NameJ},$row->{PSJ} ); print "<option value=$ProductId name=\"pid\" onmouseup=\"get_psj()\">$NameJ$psjtb</option>"; print "<tr><td><input type="text" name="price"></tr></td>"; } なんとなく、やりたいjavascript 知りたいこと:var productId_list array の中にどうやれば、 カンマの区切り入りで上の$row->{PSJ} を入れることができるのか?? function get_price () { var productId_list = [ $ProductId]; var psj_list = [ $psj ]; var pid = document.mbscalcTb.pid.value; for (var i =0; i < productIdlist.length; i++) { if (productId_list[i] == pid ) { return psj_list[i]; document.mbscalcTb.price.value= psj_list[i];} } また、他にもっといい方法があれば教えてください。宜しくお願いします。

  • ログデーターの並び替え

    ログデーターの並び替え 5月1日<>30<>http://com/<>mail@mail 5月5日<>12<>http://com/<>mail@mail 5月7日<>25<>http://com/<>mail@mail 5月10日<>50<>http://com/<>mail@mail 5月23日<>14<>http://com/<>mail@mail 上記のログデータは以下の形式で保存されています。 $date<>$no<>$url<>$mail このログの$noの部分で数値の小さい順、または大きい順に並び替えしたいのですが、 どのようにすればいいのでしょうか? open(IN, "< $logfile"); my $list = <IN>; while(<IN>){ my ($date,$no,$url,$mail) = split(/<>/); if(条件){処理} push(@data, "$_"); } close(IN); #ここで関数 sort を使って並び替えするのだと思うのですが、実際どのようにすればいいかわかりません。 open(OUT,">$logfile"); print OUT $list; print OUT @data; close(OUT); perlは簡単な改造程度しかできなくて、ここのみなさんのように専門的な知識を持っていないので、どうしてもこの並び替えがわからずに困り果てております。お手数ですが、よろしくお願いいたします。

    • ベストアンサー
    • Perl

専門家に質問してみよう