2011-12-23 10 views
3

私はスキームについての本を読んで、それは次の例があります。スキーム - 動的スコープとinfinteループ

(define map 
    (lambda (f s) 
    (if (null? s) 
     '() 
      (cons (f (car s)) 
       (map f (cdr s))))) 

(map (lambda (s) 
     (set! s '(1 2 3 4)) 
     'hello) 
    '(a b c d)) 

それはダイナミックスコープでは、我々は無限ループに入ることを言います。しかし、なぜ?私が理解できるように、我々はアプリケーションを適用した後、我々は

f = (lambda (s) 
     (set! s '(1 2 3 4)) 
     'hello) 

とs = '(a b c d)にマッピングするために到着しました。さて、最初の実行のために、我々は(car '(a b c d)fを適用します。

((lambda (s) 
    (set! s '(1 2 3 4)) 
    'hello) 
(car '(a b c d))) 

そして今、それは(1 2 3 4)するaを変更します。それで、ここにループはどこにありますか?

+1

これは質問にはまったく関係ありませんが、 'f'の呼び出しは' 'a'を' '(1 2 3 4)' 'に変更することは間違っています。 Schemeは関数パラメータを値で渡すので、 '(set!s ...)'は現在のスコープ内の変数 's'の値だけを変更できます。元のリストの 'a'を置き換えるには、関数は引数として全体のリストを取り、その上に' set-car! 'を呼び出さなければなりません。 –

答えて

1

私は何著者が意味することはf (car s)実行した後、sの値は'(1 2 3 4)になりますので、あなたがするたびに無限(map f '(2 3 4))を呼び出しますので(cdr s)の値は、'(2 3 4)になるということだと思います。

しかし、これは動的スコープの正確な描写ではないと私は思います。 sはラムダのパラメータであるため(フリー変数ではないため)、set!の影響を受けるパラメータと、mapsのパラメータは影響を受けません。したがって、動的スコープを使用しているかどうかにかかわらず、無限ループはありません。また、コードをelisp(動的スコープ)に変換すると、コードは実際には無限ループを引き起こしません。だから私はあなたの本は、動的スコープを使用して無限ループがあると言って間違っていると言うでしょう。

+0

ありがとう、しかし、私は作者が何を言いたいのか分からない。ダイナミックでは、マップ内の「s」は常に変化します。地図の呼び出しごとに新しいフレームが開き、地図が変更されます。たぶん彼は間違っていますが、私は全くアイデアを得ていません..ありがとう。 –

+3

少なくともこの例は間違っているようです。しかし、 'map'に渡された関数が'(lambda(x)(set!s '(1 2 3 4))... 'ならば、無名関数が変わるので無限ループになります's'は' map'のスコープに属しています。これは一種の実例ですが、ダイナミックスコープがどのようにローカル変数の名前のような実装の詳細を漏らすことができるかを示しています。 –

関連する問題