6

私はリストを逆にしようとしています、これが私のコードです:

(define (reverse list)
  (if (null? list) 
     list
      (list (reverse (cdr list)) (car list))))

したがって、(reverse '(1 2 3 4)) と入力すると、(4 3 2 1) として出力されるようにしたいのですが、現在はそれが得られません。私は何を間違っていますか?どうすれば修正できますか?

4

10 に答える 10

13

リストを繰り返す自然な方法は、この問題を解決するための最良の方法ではありません。@lanceryが指摘した受け入れられた回答で示唆されているように、を使用appendすることも良い考えではありません-とにかく、Schemeで自分のやり方を学んでいる場合は、自分でソリューションを実装しようとするのが最善です。 、しかし最初のヒント-パラメータ名として使用しないlistでください。これは組み込みのプロシージャであり、上書きすることになります。他の名前を使用します。たとえば、lst

結果の先頭にある各要素の結果を累積するヘルパープロシージャを使用してリストを逆にする方が簡単です。これにより、リストが逆になります。ちなみに、ヘルパープロシージャは末尾再帰です。一般的な考え方は次のとおりです。空欄に記入してください。

(define (reverse lst)
  (<???> lst '()))                       ; call the helper procedure

(define (reverse-aux lst acc)
  (if <???>                              ; if the list is empty
      <???>                              ; return the accumulator
      (reverse-aux <???>                 ; advance the recursion over the list
                   (cons <???> <???>)))) ; cons current element with accumulator

もちろん、実際にreverseは最初から実装することはありませんが、そのための組み込みの手順があります。

于 2013-02-25T00:16:19.903 に答える
2

名前付きを使用した末尾再帰アプローチlet:

(define (reverse lst)
  (let loop ([lst lst] [lst-reversed '()])
    (if (empty? lst)
        lst-reversed
        (loop (rest lst) (cons (first lst) lst-reversed)))))

これは基本的に、オスカーの回答のようにアキュムレータ引数を持つヘルパー関数を使用するのと同じアプローチです。ここでは、loopバインディング後letの let を呼び出すことができる内部関数にします。

于 2014-10-17T04:02:26.770 に答える
0

build-list手順を使用したソリューションは次のとおりです。

(define reverse
  (lambda (l)
    (let ((len (length l)))
      (build-list len
                  (lambda (i)
                    (list-ref l (- len i 1)))))))
于 2013-03-01T10:10:19.097 に答える
0

これは機能しますが、末尾再帰手順ではありません。

(define (rev lst)
 (if (null? lst)
     '()
      (append (rev (cdr lst)) (car lst))))
于 2014-04-06T07:33:18.447 に答える