6

私はRuby(2.0)を学んでいますが、これは私を驚かせました:

s = "1234"
s =~ /\d+/
$&  ==> "1234"       # as expected, $& contains the matched string
$&.slice!(-2..-1)    # should mutate string
$&  ==> "1234"       # what?
s.slice(-2..-1) 
s  ==> "12"          # as expected

このslice!メソッドは、文字列を変更することになっています。他のミューテーター メソッドも同じように動作します。私の質問: なぜこれがエラーをスローしないのですか。これはどこかに文書化されていますか?根拠はありますか?

アップデート

$&つまり、グローバル変数のように機能していないことがわかります。それへの各参照は、あたかも本当に引数のない関数であるかのように、新しいオブジェクトを与えます:

irb> $foo = "1234"
=> "1234"
irb> $foo.object_id
=> 70205012205980
irb> $foo.object_id
=> 70205012205980   # the same
irb> $&.object_id
=> 70205003531300
irb> $&.object_id   
=> 70205011619040   # different object

だから...私の質問は次のようになります:これは単にインタープリターからの「魔法」ですか、それとも$&実際にはRubyで定義できるのと同じように引数のない関数def ... endですか? そして、どうすれば違いを見分けることができますか?Python では、foo名前を使用するだけで関数を参照できます。

>>> foo
<function foo at 0x10d3117d0>

Rubyでこれを行う方法はありますか? 次に、 $& が「本当に」何であるかを確認できます (魔法ではない場合)。

4

3 に答える 3

5

Ruby C API には、フック変数と仮想変数が含まれています。README.EXTから:

フック変数を定義できます。アクセサー関数 (getter および setter) は、フックされた変数へのアクセス時に呼び出されます。

void rb_define_hooked_variable(const char *name, VALUE *var,
           VALUE (*getter)(), void (*setter)())

セッターまたはゲッターのいずれかを指定する必要がある場合は、不要なフックに 0 を指定してください。両方のフックが 0 の場合、rb_define_hooked_variable() は rb_define_variable() と同じように機能します。

getter 関数と setter 関数のプロトタイプは次のとおりです。

VALUE (*getter)(ID id, VALUE *var);
void (*setter)(VALUE val, ID id, VALUE *var);

また、対応する C 変数なしで Ruby グローバル変数を定義することもできます。変数の値は、フックによってのみ設定/取得されます。

 void rb_define_virtual_variable(const char *name,
            VALUE (*getter)(), void (*setter)())

getter 関数と setter 関数のプロトタイプは次のとおりです。

VALUE (*getter)(ID id);
void (*setter)(VALUE val, ID id);

$&は仮想変数の例です。これは で定義されてre.cおり、対応するゲッターはlast_match_getterであり、関連付けられたセッターはありません。

$&ある意味では引数のない関数であり、C で実装されているだけです。純粋な Ruby でこのような独自の仮想グローバルを定義することはできません (私が知る限り) 。独自の C 拡張)。

于 2013-02-28T21:08:18.007 に答える
2

の目的は$&何が一致したかを伝えることであるため、一致を更新できる唯一の操作であることは理にかなっています。

于 2013-02-28T17:43:59.453 に答える
1

これは興味深い質問です。jeconnerの回答と質問に対する多くのコメントは、これを行うのは役に立たないと言っているだけですが、それは質問に答えていません。それが実際のコードで行われるべきかどうかにかかわらず、OPの質問はまだ残っています。

質問に対する答えは、これは読み取り専用文字列の機能のように見えるということです。読み取り専用の文字列に破壊的な操作を適用すると、別の文字列オブジェクトが返されます。そして、それが奇妙であるというOPに同意します。むしろエラーが発生するはずです。

誰かが説得力のある説明を思いつかない限り、Ruby コアで質問するか、代わりにエラーを発生させる機能をリクエストすることをお勧めします。

于 2013-02-28T18:49:11.633 に答える