2012-02-16 15 views
2

私はスキームでループがどのように機能するかを理解するのが難しいです。このコードが実行されますが、特にどのようにループはSchemeで動作しますか?

(define (bubblesort alist) 
    ;; this is straightforward 
    (define (swap-pass alist) 
    (if (eq? (length alist) 1) 
     alist 
     (let ((fst (car alist)) (scnd (cadr alist)) (rest (cddr alist))) 
      (if (> fst scnd) 
       (cons scnd (swap-pass (cons fst rest))) 
       (cons fst (swap-pass (cons scnd rest))))))) 
    ; this is mysterious--what does the 'for' in the next line do? 
    (let for ((times (length alist)) 
      (val alist)) 
    (if (> times 1) 
     (for (- times 1) (swap-pass val)) 
     (swap-pass val)))) 

私は(let for ((はここで行うことになっているかを把握することができない理由を私は知らない、と最後の行に2番目でfor発現も入れてオフビットであります - 私は通訳者がforが1つの議論しか取らないと不平を言いましたが、ここでは2つを取るようです。

ここで何が起こっているかについてのご意見はありますか?

答えて

11

これはforループではありません。その名前はletです。それは、forという関数を作成して呼び出します。 「ループ」動作は、関数の再帰によって引き起こされます。関数loopを呼び出す方がより慣れています。例えば。

(let loop ((times 10)) 
    (if (= times 0) 
    (display "stopped") 
    (begin (display "still looping...") 
      (loop (- times 1))))) 

これは実際for言語機能を使用してちょうどあなたが簡単に再帰関数を書くことができますletのバリエーションを使用していない

(letrec ((loop (lambda (times) 
       (if (= times 0) 
        (display "stopped") 
        (begin (display "still looping...") 
          (loop (- times 1))))))) 
    (loop 10)) 
+0

多くのおかげで、私はあなたが説明したように、名前付きレットを拡張し、今私にとってははるかに理にかなっています。 –

5

のようなものに拡大します。 letに関するthisのドキュメントを参照してください(2番目のフォームです)。何が起こっている

はこのletフォームは、それが与えられた引数リスト(timesval)とのプロシージャに(この場合はforに)渡された名前を結合し、初期値でそれを呼び出すことです。本文中のバインドされた名前の使用は、再帰呼び出しです。

ボトムライン:forはここでは重要ではありません。それはちょうど名前です。名前をfooに変更しても問題はありません。ラケットには実際のforループがあり、それについてはhereを読むことができます。

関連する問題