2016-10-17 6 views
1

教育的理由から私はラケットを使ってコーディングしています。この場合、私の累積変数をラケットに注文する方法は?

フィルタなしでリストを入力として受け取り、最初のリストの偶数だけ別のリストを返す関数を作成する必要があるというタスクが与えられました。

私は反復プロセスのこの再帰的な定義を思い付いた:

(define (add-even lista) 
    (define (iter lista accu) 
    (cond ((null? lista) accu) 
      ((even? (car lista)) (iter (cdr lista) 
            (cons (car lista) accu))) 
      (else (iter (cdr lista) accu)))) 
    (iter lista empty)) 

それは正常に動作します。しかし、結果は逆の順序で表示されます。例:

(add-even '(1 2 3 4 5 6 7)) 
>> '(6 4 2) 

出力を入力と同じ順序で表示するにはどうすればよいですか?

私は逆の機能でそれを行う方法を知っています。しかし、それはあなたがiter手続きなしでそれを行うことができますもちろん

答えて

3

...

(define (add-even lista) 
    (cond ((null? lista) empty) 
     ((even? (car lista)) (cons (car lista) (add-even (cdr lista)))) 
     (else (add-even (cdr lista))))) 

(add-even '(1 2 3 4 5 6 7)) 
; => '(2 4 6) 

..非常に効率的な方法ではありませんしかし、私はあなたのadd-even手続きの末尾再帰を保つためにそれを使用していると仮定します。その場合は、その後...


あなたaccuは、あなたのconsチェーンの「穴」を埋める(リストの代わりに)手順することができます。計算の最後にaccuを返す代わりに、最後の値を入力します。この場合はemptyで、代わりにidentityで初期化します。

私は今あなたが末尾再帰を取得し、あなたが前方の順序でリストを作るので

(define (add-even lista) 
    (define (iter lista accu) 
    (cond ((null? lista) (accu empty)) 
      ((even? (car lista)) (iter (cdr lista) 
            (λ (rest) (accu(cons (car lista) rest))))) 
      (else (iter (cdr lista) accu)))) 
    (iter lista identity)) 

(add-even '(1 2 3 4 5 6 7)) 
; => '(2 4 6)

を変え、あなたのコードの一部を示すために、太字を使用。どのように動作するかを確認するために、この評価を進めることをお勧めします。これはcontinuation passing styleです。


そして、あなたはVARSを少し

(define (add-even lista) 
    (define (iter lk) 
    (cond ((null? l) (k empty)) 
      ((even? (car l)) (iter (cdr l) 
           (λ (rest) (k (cons (car l) rest))))) 
      (else (iter (cdr l) k)))) 
    (iter lista identity)) 

(add-even '(1 2 3 4 5 6 7)) 
; => '(2 4 6)

の名前を変更し、それはあなたがnamed-let

(define (add-even lista) 
    (let iter [(l lista)(k identity)] 
    (cond ((null? l) (k empty)) 
      ((even? (car l)) (iter (cdr l) 
           (λ (rest) (k (cons (car l) rest))))) 
      (else (iter (cdr l) k))))) 

(add-even '(1 2 3 4 5 6 7)) 
; => '(2 4 6)
を使用した場合でも、もう少しクリーンアップならば、おそらく手順が良いだろう

...そしてそれはcle ANSアップ我々はまた、短い関数を作成するために使用することができ、内蔵for/list#:when句でcomposeとラケットで

(define (add-even lista) 
    (let iter [(l lista) (k identity)] 
    (cond ((null? l) (k empty)) 
      ((even? (car l)) (iter (cdr l) (compose k (curry cons (car l))))) 
      (else (iter (cdr l) k))))) 

(add-even '(1 2 3 4 5 6 7)) 
; => '(2 4 6)
0

curryを、使用している場合でもより:

(define (onlyeven lst) 
    (for/list ((i lst) #:when (even? i)) 
    i)) 

(onlyeven '(1 2 3 4 5 6 7)) 
; => '(2 4 6) 
+0

ないだろう 'フィルター「もう少しダイレクトですか? – naomik

+0

OPは、特にフィルタなしで関数を作成したい(質問の2番目のパラグラフの最初の文を参照)。 – rnso