5

異常に思われるものに出くわしたので、その理由を説明できる人がいるかどうか疑問に思っていました。

1.8.7 :001 > some_str = "Hello World"
 => "Hello World" 
1.8.7 :002 > some_str.try(:match, /^(\w*)/)
 => #<MatchData "Hello" 1:"Hello"> 
1.8.7 :003 > $1
 => nil 
1.8.7 :004 > some_str.match(/^(\w*)/)
 => #<MatchData "Hello" 1:"Hello"> 
1.8.7 :005 > $1
 => "Hello" 

グローバル変数$1が最初に設定されていない理由がわかりませんが、2番目に設定されています。洞察はありますか?

4

2 に答える 2

3

tryと定義されている

def try(method, *args, &block)
  send(method, *args, &block)
end

もちろん、nilを返すだけのnilを除きます。なぜこれが重要なのですか?正規表現グローバルは実際のグローバルではないため、メソッドごとおよびスレッドごとに維持されます(rubyソースを熟読することでこれを確認するのは簡単です)。matchグローバルを介して呼び出すとtry、のスコープに設定されますがtry、次の場合はトップレベルに設定されます。これを確認するのは簡単です

def do_match string, regexp
  string =~ regexp
  $1
end
do_match "Hello World", /^(\w*)/ #=> returns 'Hello'
$1 #=> returns nil 
于 2012-07-11T22:12:13.963 に答える
3

try実装方法をお見せしましょう。自分で確認したい場合は、activesupportのソースをご覧ください。/lib/active_support/core_ext/object/try.rbで定義されています

class Object
  def try(*a, &b)
    if a.empty? && block_given?
      yield self
    else
      public_send(*a, &b)
    end
  end
end

これが基本的に行うことは、メソッド名と完全な引数をに送信することObjectです。public_sendsendと同じですが、パブリックメソッドの呼び出しにのみ使用できます。

だから私はあなたの問題をデバッグするためにこれを書き直しました:

class Object
  def try(*a)
    result = public_send(*a)
    puts $1.inspect
    result
  end
end

string = "Hello"
string.try(:match, /^(\w*)/)
puts $1.inspect

この出力

"Hello"
nil

それで、大きな疑問が生じます:これはルビーインタプリタのバグですか?多分。少なくとも、公式の情報源には文書化されていません。次のことを伝える参照を見つけました(グローバル変数を参照してください)。

[...]、$_ローカル$~スコープがあります。それらの名前はグローバルであるべきであることを示唆していますが、この方法の方がはるかに便利であり、これらの名前を使用する歴史的な理由があります。

$1したがって、カーネルによってグローバル変数として報告されていても、グローバル変数ではないようです。

1.9.3-p194 :001 > global_variables
 => [:$;, :$-F, :$@, :$!, :$SAFE, :$~, :$&, :$`, :$', :$+, :$=, :$KCODE, :$-K,
     :$,, :$/, :$-0, :$\, :$_, :$stdin, :$stdout, :$stderr, :$>, :$<, :$.,
     :$FILENAME, :$-i, :$*, :$?, :$$, :$:, :$-I, :$LOAD_PATH, :$",
     :$LOADED_FEATURES, :$VERBOSE, :$-v, :$-w, :$-W, :$DEBUG, :$-d, :$0,
     :$PROGRAM_NAME, :$-p, :$-l, :$-a, :$binding, :$1, :$2, :$3, :$4, :$5, :$6,
     :$7, :$8, :$9] 

念のため、この不整合をRubyバグトラッカーに転送しました。Rubyバグ#6723を参照してください

于 2012-07-11T22:12:23.760 に答える