5

違いがわかりません(不自然な例で申し訳ありません):

(define average
  (lambda (elems)

   (define length
     (lambda (xs)
      (if (null? xs)
          0
          (+ 1 (length (cdr xs))))))

   (define sum
     (lambda (xs)
      (if (null? xs)
          0
          (+ (car xs) (sum (cdr xs))))))

   (define total (sum elems))

   (define count (length elems))

   (/ total count)))

(define average
  (lambda (elems)
   (letrec ((length
              (lambda (xs)
               (if (null? xs)
                   0
                   (+ 1 (length (cdr xs))))))

            (sum
              (lambda (xs)
               (if (null? xs)
                   0
                   (+ (car xs) (sum (cdr xs))))))

            (total (sum elems))

            (count (length elems)))

     (/ total count))))

私が知る限り、それらは両方とも新しいスコープを作成し、そのスコープ内で相互に参照する 4 つのローカル変数を作成し、本体を評価して返します。

ここで何か不足していますか、それともスコープ付きsletrecと同義ですか?define

これは実装に依存する可能性があることを知っています。Lips の基礎を理解しようとしています。

4

2 に答える 2

8

defineコードのとletrecバージョンの間に類似点があることは正しいです。しかし、悪魔は細部に宿ります。R5RS では、internaldefineletrecセマンティクスがあります。R6RS では、internaldefineletrec*セマンティクスがあります。

違いは何ですか?あなたのコードは実際にこの違いを強調しただけです。Zhehao's answer が言及しているように、 and と同じ内の and の定義は正しくありtotalません: andは、 andの値を評価するまでにバインドされることが保証されていません。これらの変数のバインドは、そのままになることが保証されていないためです。右に。countletreclengthsumlengthsum(length elems)(sum elems)

letrec*に似てletrecいますが、左から右への保証があります。したがって、 を に変更letrecletrec*ても問題ありません。

さて、最初のコメントに戻ります。R5RS の内部でdefineletrecセマンティクスが使用されているためdefine、コードのバージョンでさえ R5RS 実装では正しくありませんが、セマンティクスを持つ R6RS 実装では問題ありませんletrec*

于 2012-07-13T02:51:36.783 に答える
4

let/letrec と define は両方とも、ローカル スコープの定義を作成します。ただし、内部になく、明示的な begin ステートメントがない場合は、 let/letrec の方が便利です。たとえば、次のコードは let マクロを使用しています。

(define (test) (let ((x 1)) x))

ローカル スコープの定義を使用する同じコードは、次のようになります。

(define test (lambda () (define x 1) x))

これは一種の不自然な例ですが、一般的に let マクロを使用してローカル バインディングを行う方がより機能的であると考えられています。

また、サンプル コードでは letrec が正しく使用されていません。letrec 宣言内に定義する必要はありません (実際、そこにあるべきではありません)。

于 2012-07-13T02:31:21.643 に答える