忍者ブログ

ぢみへんプログラミング日誌

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

紛らわしいRubyの変数スコープ

Ruby1.8.7ではコードブロックとラムダの引数と変数の扱いが紛らわしい。
ブロック(もしくはラムダ)の引数、あるいはブロック内(またはラムダ内)の変数が、そのブロック(もしくはラムダ)外の変数と同名である場合は、外にある変数が使用される。

以下実例。

C:\Users\admin>irb
irb(main):001:0> a = 1
=> 1
irb(main):002:0> def fnc1
irb(main):003:1> a = 2
irb(main):004:1> end
=> nil
irb(main):005:0> fnc1
=> 2
irb(main):006:0> a
=> 1
irb(main):007:0> def fnc2(a) a = 3 end
=> nil
irb(main):008:0> fnc2(4)
=> 3
irb(main):009:0> a
=> 1
irb(main):010:0> p1 = lambda{|x| a += 1}
=> #
irb(main):011:0> p1.call(5)
=> 2
irb(main):012:0> a
=> 2
irb(main):013:0> p2 = lambda{|a| a+= 2}
=> #
irb(main):014:0> p2.call(5)
=> 7
irb(main):015:0> a
=> 7
irb(main):016:0> (1..10).each{|i| a += i}
=> 1..10
irb(main):017:0> a
=> 62
irb(main):018:0> (1..10).each{|a| a += 1}
=> 1..10
irb(main):019:0> a
=> 11


見ての通り、メソッドの引数やメソッド内の変数に関しては、メソッド外に同名の変数があっても全く互いに影響を及ぼしあわない。
ところがブロックやラムダの場合、外部変数のスコープがブロック(ラムダ)内のスコープに浸食してしまう。特に驚くのは引数の名前を外部変数と同じにした場合で、このときも引数が独自のローカル変数ではなく、外部変数の参照を意味するので、C/C++やPHPあたりに慣れた頭にはびっくりである。

引数名の扱いに関しては1.9系で改善された。

irb(main):001:0> a = 1
=> 1
irb(main):002:0> p1 = lambda{|x| a += 1}
=> #
irb(main):003:0> p1.call(5)
=> 2
irb(main):004:0> a
=> 2
irb(main):005:0> p2 = lambda{|a| a += 2}
=> #
irb(main):006:0> p2.call(5)
=> 7
irb(main):007:0> a
=> 2
irb(main):008:0> (1..10).each{|i| a += i}
=> 1..10
irb(main):009:0> a
=> 57
irb(main):010:0> (1..10).each{|a| a += 1}
=> 1..10
irb(main):011:0> a
=> 57


見ての通り、引数に外部変数と同名の変数を割り当てた場合は、その変数はブロック(もしくはラムダ)内で完全にローカル変数としてのスコープを持っていて、外部とは遮断されていることが分かる。
PR

COMMENT

NAME
TITLE
MAIL (非公開)
URL
EMOJI
Vodafone絵文字 i-mode絵文字 Ezweb絵文字
COMMENT
PASS (コメント編集に必須です)
SECRET
管理人のみ閲覧できます
 
  

カレンダー

02 2024/03 04
S M T W T F S
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

フリーエリア

最新CM

バーコード

ブログ内検索

Copyright ©  -- ぢみへんプログラミング日誌 --  All Rights Reserved

Design by CriCri / Material by petit sozai emi / powered by NINJA TOOLS / 忍者ブログ / [PR]