2
(defun highest (lat)
    (cond
        ((null lat) nil)
        ((null (cdr lat)) (car lat))
        (T (higher (car lat) (highest (cdr lat))))))

(defun higher (a1 a2)
    (cond
        ((> a1 a2) a1)
        (T a2)))

この関数は期待どおりに機能します。

> (highest '(3 5 1 2 3))    
3. Trace: (HIGHEST '(3 5 1 2 3))
4. Trace: (HIGHEST '(5 1 2 3))
5. Trace: (HIGHEST '(1 2 3))
6. Trace: (HIGHEST '(2 3))
7. Trace: (HIGHEST '(3))
7. Trace: HIGHEST ==> 3    
6. Trace: HIGHEST ==> 3
5. Trace: HIGHEST ==> 3
4. Trace: HIGHEST ==> 5    
3. Trace: HIGHEST ==> 5

しかし、パラメータを次のように変更すると&rest:

(defun highest (&rest args)
    (cond
        ((null args) nil)
        ((null (cdr args)) (car args))
        (T (higher (car args) (highest (cdr args))))))

同じようには動作しません。

> (highest 3 5 1 2 3)
3. Trace: (HIGHEST '3 '5 '1 '2 '3)
4. Trace: (HIGHEST '(5 1 2 3))
4. Trace: HIGHEST ==> (5 1 2 3)
*** - >: (5 1 2 3) is not a real number

編集: 申し訳ありませんが、2 番目のケースでは引数をアトムに渡すことを忘れていました。質問を編集して、より明確にしました。

4

2 に答える 2

5

Try to evaluate (trace highest) before calling (highest 3 2 10). You will then see that the second call looks like this: (highest '(2 10)) Then the &rest parameter sees one object which happens to be a list.

To correct this, use APPLY. APPLY is like funcall but its last argument must be a list and is treated as if it was 'spliced onto' the function call. Like this: (apply #'highest (cdr args))

于 2013-04-02T22:25:17.703 に答える
3

&restフォームは、リスト自体として渡された残りのすべてのパラメーターを収集します。の場合、highest (&rest args)実際argsには要素を持つリスト、リストです。つまり、呼び出しでは、args値は((3 2 10))です。

highestwith修飾子の 2 番目のバージョンは、1 つの要素を持つ単なるリスト (たまたまリスト) のように、&rest常に条件の 2 番目のテストに入ります。リスト自体であるargsの最初の要素を返します。args(3 2 10)

両方の構造の違いは、リストをパラメーターとして渡す最初のバージョンでは、関数はリストを関数の唯一のパラメーターとして受け取ることです。の場合&rest、すべての引数 (この場合は 1 つだけ) がリストにまとめられます (この場合は 1 つの要素のみ)。

EDIT : あなたの編集によると、Thomas がコメントで述べているように、 using は、再帰的に呼び出す&rest必要があることを意味します。applyこれは正しい実装です:

(defun highest (&rest args)
    (cond
        ((null args) nil)
        ((null (cdr args)) (car args))
        (T (higher (car args) (apply #'highest (cdr args))))))

apply(最後の行に注意してください)。

于 2013-04-02T22:11:48.037 に答える