0

2 つの数値を取り、最初の数値から 2 番目の数値までのリストを準備するメソッドを作成するにはどうすればよいですか。最初の数値は常に正で、2 番目の数値より小さいですか? 次のことを試しましたが、以前の値を保持するためにSchemeでグローバル変数を使用する方法がわかりません。

(define preplist  
  (let ((temp '())) 
   (lambda (x y) 
     (cond ((= x y) (append temp (list x)))
           (else (append temp (list x))
                 (display x)
                 (preplist (+ x 1) y))))))

期待される結果: (preplist 3 7) => (3 4 5 6 7)

誰かがこの問題を解決するのを手伝ってくれませんか?

4

2 に答える 2

1

コードにはいくつかの間違いがあります。まず、結果を格納するために a で定義されたグローバル変数は必要ありませんlet。再帰を進めるときに答えを構築するだけで十分です。appendこの場合は使用しないでください。ソリューション テンプレートに厳密に従っていればcons、出力リストを作成するのに a で十分です。

新しいリストを再帰的に構築するためのレシピに固執する必要があります。これは、そのレシピを使用して問題を解決する方法です。おそらく、次のようにもう少し慣用的です。

(define preplist
  (lambda (x y)
    (cond ((> x y)                          ; if the exit condition is met
           empty)                           ; then return the empty list
          (else                             ; otherwise
           (cons x                          ; cons the current element
                 (preplist (add1 x) y)))))) ; and advance the recursion

まったく異なるアプローチは、末尾再帰ソリューションを作成することです。一定量のスタックが使用されるため、これはより効率的です。上記の設計レシピには従いませんが、あなたが考えていたソリューションに多少似ていますが、これはグローバル変数を使用せず (let反復の名前のみ)、ソリューションが蓄積されることに注意してください。パラメータとして渡されます:

(define (preplist x y)
  (let loop ((i y)             ; named let for iteration
             (acc empty))      ; define and initialize parameters
    (if (> x i)                ; if exit condition is met
        acc                    ; return accumulated value
        (loop (sub1 i)         ; otherwise advance recursion
              (cons i acc))))) ; and add to the accumulator

もちろん、コメントで@dyooが指摘しているように、実際の設定では、rangeプロシージャと基本的に同じことを行う組み込みプロシージャを使用しpreplistます。

于 2013-03-19T13:40:00.307 に答える
1

(x, y) の解は次のように計算できます: x を (x+1, y) の前に置きます。したがって、これは明らかに再帰的です。このような:

(define (preplist x y)
  (if (= x y)
      (list y)
      (cons x (preplist (+ x 1) y))))

ほら、それは動作します:

> (preplist 1 4)
(1 2 3 4)
> (preplist 5 7)
(5 6 7)
于 2013-03-19T06:32:35.213 に答える