kiyokaのブログアーカイブ

Archive of old blog posts

Ruby 1.8.x対応を見送った

私がRubyで書いているLisp方言、 [Nendo]について。

[Nendo]でmapをネストして2重ループを形成すると変な動作をする。何だこれは。 クロージャのレキシカル変数の内容がどんどん破壊される。 小一時間ほど追いかけた結果、Ruby 1.8.xのクロージャの問題だということが発覚した。 結論としては、Ruby 1.8.xのクロージャはレキシカルクロージャではないことを自分が忘れていたのが問題。… img [Nendo]のlambdaはRubyのクロージャにそのままマッピングするようになっているため、Rubyのクロージャがレキシカルクロージャでない限り[Nendo]のlambdaが正常に動かないのも当然だった。

ちょっとテストとしてはわかりにくいかも知れないが、こんなRubyコードで実験した。

#!/usr/local/bin/ruby

lambda1 = lambda { |val|
  printf( "(0) = %s\n", val )
  val = 'A'
  printf( "(1) = %s\n", val )
  lambda2 = lambda { |val|
    printf( "(2) = %s\n", val )
  }
  lambda2.call( 'B' )
  printf( "(3) = %s\n", val )
  val
}
lambda1.call( 'START' )
  • Ruby 1.9.2devでは期待通り
    $ ruby --version
    ruby 1.9.2dev (2009-07-18 trunk 24186) *powerpc-darwin9.5.0*
    $ ./t.rb
    (0) = START
    (1) = A
    (2) = B
    (3) = A
    

    (3)の箇所で値 ‘A’ が保持されている

  • Ruby 1.8.7では…
    bash-3.2$ ruby --version
    ruby 1.8.7 (2009-06-12 patchlevel 174) *powerpc-darwin9.5.0*
    bash-3.2$ ./t.rb
    (0) = START
    (1) = A
    (2) = B
    (3) = B
    

    (3)の箇所で値 ‘B’ になる。

Ruby 1.9.2がもうすぐ正式に出る時期なので、まじめにRuby 1.8.xでも動く様にするのはあきらめよう。 ちなみに、JRubyとかはどっちなんだろう。今度確認しよう。