トップ «前の日記(2014-03-23) 最新 次の日記(2014-05-28)» 編集

誰も褒めてくれないから自画自賛する日記

nu-chon.org  「ぬ」あんてな  「ぬ」wiki  RSS
2000|01|02|03|04|05|06|07|08|09|10|11|12|
2001|01|02|03|04|05|06|07|08|09|10|11|12|
2002|01|02|03|04|05|06|07|08|09|10|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|06|07|
2012|01|03|05|06|08|09|
2013|01|08|09|
2014|01|03|05|08|12|
2015|01|04|09|10|
2016|01|
Sapporo RubyKaigi 02
Sapporo RubyKaigi 03
RubyKaigi
Sapporo RubyKaigi 2012
RubyKaigi 2013
2014年
3月
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

2014-03-26 [長年日記]

mit-schemeの内部defineとRubyの内部def

SICPを読んでいて、面白いなぁ、と思ったので、ちょっとメモします。

Exercise 4.19で、以下のコードを実行した時、結果は何が期待されるか、という問題。

(let ((a 1))   ;; (1)
  (define (f x)
    (define b (+ a x))   ;; (2)
    (define a 5)  ;; (3)
    (+ a b))
  (f 10))

これはインタプリタの実装依存ですが、mit-schemeの場合は、

Unbound variable: a

というエラーになります。

雰囲気的には、letの内部で定義されているdefine (2),(3)がmit-schemeでは、以下の様な感じで解釈されるからっぽいです。

(let ((a 1))
  (define (f x)
    (let ((b '*unassigned)
           (a '*unassigned))
      (set! b (+ a x))
      (set! a 5)
      (+ a b))))

つまり、let で a = 1となっているけど、(2)の(define b (+ a x))が解釈されるタイミングでは、(+ a x)の"a"は、(1)のletで宣言された"a"ではなく、同じフレーム内で定義された(3)の(define a 5)の"a"が対象となる。しかし、あくまでも a = 5となるのは (define a 5)となるタイミングになるので、(2)の(define b (+ a x))のタイミングでの"a" は「宣言されているけど未設定」の状態になり、エラー、という解釈になるらしい。

で、思い出したのが、Ruby。

def aaa
   p defined?(bbb) #(1)
   p defined?(ccc) #(2)
   def bbb;1;end  #(3)
   p defined?(bbb) #(4)
end

というメソッドを定義して呼び出すと、

> aaa
"method"  #(1)の結果
nil #(2)の結果
"method"  #(4)の結果
=> "method" 

となり、最初の(1)の段階では (3)の def bbb が登場する前なのに、実行すると "method"として認識されている。

同じや〜。RubyはMatz LISPや〜。

他の言語だとどうなのかは不勉強なため知りません。

そんな感じです。

補足

ただし、Rubyで以下のコードを実行した場合、schemeとは異なります。

def bbb; 2; end
def aaa
  p defined?(bbb)
  p bbb
  def bbb; 1; end
  p defined?(bbb)
  p bbb
end
aaa
bbb
> aaa
"method" 
2
"method" 
1
=> 1 

>   bbb
=> 1

aaaの外側で定義したbbbがaaaの内部で参照可能ですし、def bbbの後は、このbbbが参照されますね。これは、Rubyのdef内部で定義したdefはその外側でdefで定義したことと同義になるため、bbb自体が上書きされるためです。(この動きについては、メタプログラミングRubyに記述があったような気がします。)

そういう意味では挙動が異なりますね。

本日のツッコミ(全2件) [ツッコミを入れる]
(2014-03-26 13:08)

Rubyのコードの#(2)が間違っていたので修正しました。

(2014-03-26 13:25)

補足も追記したよん


2000|01|02|03|04|05|06|07|08|09|10|11|12|
2001|01|02|03|04|05|06|07|08|09|10|11|12|
2002|01|02|03|04|05|06|07|08|09|10|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|06|07|
2012|01|03|05|06|08|09|
2013|01|08|09|
2014|01|03|05|08|12|
2015|01|04|09|10|
2016|01|

2014年
3月
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

Copyright (C)2005-2015 nu-chon.org.