2

GNUClISPを使用してCommonLispでプログラムを作成してコンパイルしようとしています。次のようなリストを入力したいと思い(A(B (C) ()) (D (E) (F (G) ())))ます。最初の単語に応じて、注文前、注文中、または注文後のトラバーサルを印刷します。例:

(pre '(A(B (C)... etc))

ロジックをClisp表記に入れるのに問題があります。私は現在次のコードを持っています:

(defun leftchild (L)(cadr L))

(defun rightchild (L)(caddr L))

(defun data (L)(car L))

(defun pre (L)(if (null L) '()((data L)(pre(leftchild L))(pre(rightchild L)))))

... similar in and post functions

pre関数でラムダを使用する必要があるというコンパイルエラーが発生します。これはdouble((コマンドを期待しているためデータの前にありますが、そこに何を置くべきかわかりません。再帰ループを妨げるため、condは機能しないと思います。また、データLはそのまま印刷されますか?コンパイラはを認識しませんでした(print (data L))

私はこのコードに1週間以上取り組んでおり、自分でトラブルシューティングを試みていますが、途方に暮れています。誰かが私が間違っていることを説明してくれれば幸いです。

私が持っているもう1つの質問は、コンパイルされたファイルを実行すると、funcallエラーが発生する代わりにプログラムが実行されるように、プログラムにユーザーに(pre'(A ...など))を入力するように求める行を表示させる方法です。 ?

お時間をいただきありがとうございます。

4

1 に答える 1

1

簡単な答え:を使用する場合は、後件部と代替の場合に複数のフォームを使用するためにがif必要になることに注意してください。progn


長い答え–訪問したノードをリストに蓄積してトラバースする方法についても説明します。

これは宿題だと思うので、完全な解決策は提供しませんが、あなたの質問はあなたが基本的に正しい考えを持っていることを示しているので、これを行う簡単で慣用的な方法を紹介します。

まず、その通りです。引用符で囲まれていない形式の車は関数である必要があるため、基本的に、関数(またはマクロ、特殊形式...)ではなく、すべてが評価される、のようなものは次のようになります(foo ...)fooエラー。condこれは、特別なフォームやマクロ(たとえば、など)の内部には当てはまらないことに注意してください。これらは評価ルールを変更する可能性があり、見た目がすべて(foo bar)通常の評価ルールによって評価されるフォームである必要はありません。最も簡単な例はquote、です。これは、引数を未評価で返すだけなので、エラー(quote (foo bar))にはなりません。

さて、あなたの問題について:

簡単な解決策は、アキュムレータと、ツリーをトラバースし、アキュムレータに値をプッシュする再帰ヘルパー関数を用意することです。このようなもの:

(defun pre (node)
  (let ((result (list)))
    (labels ((rec (node)
               (cond (...
                      ...
                      ...))))
      (rec node)
      (nreverse result))))

は、実際のlabels再帰を実行するローカルヘルパー関数を導入するだけで、アウターletはノード値を収集するためのアキュムレータを提供します。このソリューションは、結果をリストとして返します。各ノードの値を出力するだけの場合は、アキュムレータやヘルパー関数は必要ありません。プッシュする代わりに印刷するだけで、ヘルパーをトップレベルの関数にします。

再帰が停止するベースケースが必要になることを忘れないでください。で確認する必要がありcondます。次に、サブツリーごとに再帰的な手順が必要になり、ノードの値を結果にプッシュする必要があります。これらの手順を実行する順序によって、順序前、順序内、または順序後のトラバーサルを実行するかどうかが決まります。あなたのコードは、あなたがすでにこの原則を理解していることを示しているので、Lispコードでそれを機能させる必要があります。を使用して値をにpushプッシュし、ノードが空でないリストであるかどうかを確認できます。空のリストには何もする必要がないため、基本的にはで1つのテストのみが必要ですが、コードで行ったように、ノードがであるかどうかを明示的に確認することもできます。resultconspcondnull

于 2011-10-10T08:55:00.610 に答える