4

だから私は鉱山の友人から聞いたこのScheme言語を学ぼうとして立ち往生しています。彼が私がすべきだと言ったことは、小さなことから始めて、それを本当に理解するために自分の道を進んでいくことです。それで、彼が持っていたスキームプログラミングについて簡単に説明している教科書を読んだ後、私はそれがどのように機能するかについて少し戸惑いました。

私が尋ねようとしていることのほとんどは、という関数に定義を追加したい場合、私が定義したいくつかのリストから「偶数」としましょう。

(DEFINE list0 (LIST 'j 'k 'l 'm 'n 'o 'j) )
(DEFINE list1 (LIST 'a 'b 'c 'd 'e 'f 'g) )
(DEFINE list2 (LIST 's 't 'u 'v 'w 'x 'y 'z) )
(DEFINE list3 (LIST 'j 'k 'l 'm 'l 'k 'j) )
(DEFINE list4 (LIST 'n 'o 'p 'q 'q 'p 'o 'n) )
(DEFINE list5 '((a b) c (d e d) c (a b) )
(DEFINE list6 '((h i) (j k) l (m n)) )
(DEFINE list7 (f (a b) c (d e d) (b a) f) )

以下のタスクのようになります:evens

これは、私が信じている加算関数をすでに作成しています。

(DEFINE (adder lis)
    (COND
        ((NULL? lis) 0)
        (ELSE (+ (CAR lis) (adder (CDR lis))))
))

以下のタスクのように実行したい場合でも、の定義は何でしょうか。

EVENS:(evens 1st)は、1番目に取得された偶数の要素から形成された新しいリストを返す必要があります。

(evens '(a b c d e f g))
which would/should return:
(b d f)

と:

(evens (LIST 's 't 'u 'v 'w 'x 'y 'z))
which would/should return:
(t v x z)

と:

(evens '(f (a b) c (d e d) (b a) f) )
which would return:
((a b) (d e d) f)

および(evens'())と(evens'(a))の両方

空のリストを返します。

私は練習するために誤ってトレイルを通り抜けてきましたが、私は完全に道に迷っています。前もって感謝します

さて、私は私が解決しようとしている私の例に再帰関数を思いついたと思います:

 (define mylist '(1 2 3 4 5 6 7))
 (define (evens lst)
 (define (do-evens lst odd)
     (if (null? lst)
 lst
     (if odd
         (do-evens (cdr lst) #f)
         (cons (car lst) (do-evens (cdr lst) #t)))))
         (do-evens lst #t))

何かご意見は?

4

3 に答える 3

2

まず第一に、adder関数はあなたの質問とは何の関係もありませんよね?

機能について考えてくださいevens。あなたはすでにそれを言って(evens '())おり(evens '(a))、空のリストを返す必要があります。何を(evens '(a b))返す必要がありますか?どう(evens '(a b ...))ですか?再帰を設定する方法がわかりますか?

于 2012-11-09T22:34:03.797 に答える
2

OK、リストを反復処理する再帰関数を実行し、返す要素を選択して他の要素を選択しないようにするには、基本的なパターンは次のようになります。

(define (recur l)
  (cond
    ((null l) '())
    ((??????) (cons (car l) (recur (cdr l))))
    (else (recur (cdr l)))))

それは何ですか

  1. リストはnullですか?nullを返します。
  2. リストがnullでない場合、リストの最初の項目を保持する必要がありますか?(recur (cdr l))わかりました、それを保持して、すべてのリターンに追加しましょう
  3. それ以外の場合は、返されたものをすべてrecur (cdr l)返します。

これが明確になることを願っています。単純な再帰リスト関数は、リストの最初の要素のみを調べ、それをどう処理するかを決定してから、リストの残りの部分で自分自身を再度呼び出します。再帰は、ある意味では、データの最初の部分のみを処理し、別の関数に残りのデータを心配させることによって計算を単純化する方法です(他の関数は、実際には最初に呼び出した関数と同じですが、それについて心配しないようにしてください)。たとえば、偶数のアイテムのみを返す再帰関数は、次のようになります。

(define (even-numbers l)
  (cond
    ((null? l) '())
    ((even? (car l)) (cons (car l) (even-numbers (cdr l))))
    (else (even-numbers (cdr l)))))

そうは言っても、あなたのケースはもう少し複雑です。最初の要素を削除してから、関数を連続して呼び出すたびに、最後の呼び出しとは逆の操作を行う必要があります。

これを行う1つの方法は、ブールステータスを渡し、毎回それを反転させることです。偶数関数は状態をとらないため、別の内部関数を定義して、それを繰り返す必要があることに注意してください。

(define (evens l)
  (let loop ((lst l) (keep #f))
      (cond
         ((null? lst) '())
         ((eq? keep #t) (???????)
         (else (loop (cdr l) #t)))))

(???????)前の例を考えると、自分で何が起こるかを理解できるはずです。私はあなたのために少しやりすぎだと思います。

これを行う別の方法は、相互再帰関数の偶数オッズを使用することです。それを考慮してください

  1. evensは、最初の要素を破棄してからリストを処理する関数であり、毎回、前回とは逆の(保持または破棄)を実行します。
  2. オッズは、最初の要素を保持してからリストを処理する関数であり、毎回、前回とは逆の(保持または破棄)を実行します。

これは、あなたが定義できることを意味します

  1. 最初の要素を無視し、リストの残りの部分でオッズを呼び出す関数としての偶数。
  2. 最初の要素を保持し、リストの残りの部分で偶数を呼び出し、最初の要素を結果の先頭に置く関数としてのオッズ

それは次のようになります

(define (evens l)
  (cond
    ((null? l) '())
    (else (odds (??????)))))

(define (odds l)
  (cond
    ((null? l) '())
    (else (cons (car l) (evens (??????))))))

うまくいけば、これはある程度意味があります。

Schemeでの再帰を本当に理解したい場合は、「TheLittleSchemer」のコピーを購入して作業を開始してください。

于 2012-11-11T06:45:29.337 に答える
0

これはどうですか:

(define (evens l)
  (cond
   ((null? l) '())
   ((null? (cdr l)) '())
   (else (cons (cadr l) (evens (cddr l))))))

しかし、私は偶数とオッズの答えが好きです!

于 2014-07-17T12:43:57.657 に答える