2017-07-12 4 views
0
(define (sqrt x) 
  (define (good-enough? guess x) 
    (< (abs (- (square guess) x)) 0.001)) 
  (define (improve guess x) 
    (average guess (/ x guess))) 
  (define (sqrt-iter guess x) 
    (if (good-enough? guess x) 
        guess 
        (sqrt-iter (improve guess x) x))) 
  (sqrt-iter 1.0 x)) 

私は内部ブロック構造の周りに頭を包んでいるようには見えません。 defineの構文が次のとおりである場合(define プロシージャarg arg本文)。どのようにしてトップレベルの定義内の他のすべてのローカルスコープ変数を定義することができますか?ブロック構造の内部定義

定義には例外がありますか?

+0

使用しているスキームを知っておくと便利です。また、[この質問](https://stackoverflow.com/questions/20896471/decent-way-of-nested-definition-in-scheme)とその回答を確認することもできます。 – pdoherty926

答えて

0

defineの構文は(define procedure arg .. body)ではありません。 (define name (lambda args defines ... body1 bodyn ...))のショートカットである(define (name . args) defines ... body1 bodyn ...)のいずれかです。 x ...は0以上を意味するので、(lambda (a b) (+ a b))は問題ありませんが、(lambda (a b) (define (test) (+ a b)))は正しくありません。

内部defineは、lambda構文で処理されます。基本的にはletrecに書き換えられます。だから、

(define (sqrt x) 
    (define (good-enough? guess x) 
    (< (abs (- (square guess) x)) 0.001)) 
    (define (improve guess x) 
    (average guess (/ x guess))) 
    (define (sqrt-iter guess x) 
    (if (good-enough? guess x) 
     guess 
     (sqrt-iter (improve guess x) x))) 
    (sqrt-iter 1.0 x)) 

は次のようになります。

(define sqrt 
    (lambda (x) 
    (letrec ((good-enough? (lambda (guess x) 
          (< (abs (- (square guess) x)) 0.001))) 

      (improve (lambda (guess x) 
         (average guess (/ x guess)))) 
      (sqrt-iter (lambda (guess x) 
          (if (good-enough? guess x) 
           guess 
           (sqrt-iter (improve guess x) x))))) 
     (sqrt-iter 1.0 x)))) 

明らかローカルdefineを使用する理由は、それが平らとletrecより読みやすく維持することです。実装のさまざまな部分で扱われる全く異なる獣であっても、同じ名前を持つことはスキームプログラマーのための単純化ですが、スキーマ実装の仕組みを理解しようとすると理解しにくくなります。

+0

R6RSとR7RSでは、 'define'による内部定義はletrecではなく、letrec *として書き直されています。後の定義では、前の定義を評価できます。 –