Warum ist der Ausgang anders?
Ein Proc in Ruby hat lexikalischen Geltungsbereich. Das heißt, wenn eine Variable gefunden wird, die nicht definiert ist, wird sie in dem Kontext aufgelöst, in dem die Prozedur definiert, nicht genannt wurde. Dies erklärt das Verhalten Ihres Codes.
Sie können sehen, dass der Block vor der Regexp definiert ist, und dies kann zu Verwirrung führen. Das Problem beinhaltet eine magische Ruby-Variable, und es funktioniert ganz anders als andere Variablen. Citing @JörgWMittag
Es ist ziemlich einfach, wirklich: der Grund, warum $ SAFE verhält sich nicht wie man es von einer globalen Variablen erwarten ist, weil es nicht eine globale Variable ist. Es ist ein magisches Einhorn dingamajiggy.
Es gibt durchaus ein paar jener magische Einhorn thingamajiggies in Ruby, und sie sind leider nicht sehr gut dokumentiert (nicht dokumentiert, in der Tat), wie die Entwickler der alternativen Ruby-Implementierungen auf die harte Tour herausgefunden. Diese Thinga-Jiggies verhalten sich alle unterschiedlich und (scheinbar) inkonsistent, und so ziemlich die einzigen beiden Dinge, die sie gemeinsam haben, ist, dass sie wie globale Variablen aussehen, sich aber nicht wie diese verhalten.
Einige haben lokalen Anwendungsbereich. Einige haben thread-lokalen Umfang. Manche verändern sich auf magische Weise, ohne dass jemand ihnen etwas zuschreibt. Einige haben eine magische Bedeutung für den Interpreter und ändern, wie sich die Sprache verhält. Einige haben andere seltsame Semantiken an sich.
Wenn Sie wirklich nach oben sind genau das zu finden, wie die $1
und $2
Variablen arbeiten, gehe ich davon aus, die nur „Dokumentation“ finden Sie ist rubyspec, dass eine Spezifikation für Rubin ist die harte Art und Weise von den Leuten Rubinus getan. Habt ein nettes Hacken, aber seid auf den Schmerz vorbereitet.
Gibt es eine Möglichkeit, einen Block, um von einem anderen Zusammenhang mit $ 1, $ 2 Variablen Setup den richtigen Weg zu gsub?
Sie erreichen, was Sie mit dieser nach entsprechenden Änderungen wollen (aber ich wette, dass Sie bereits wissen, dass)
require 'pp'
def hello(z)
#z = proc {|m| pp $1}
"hello".gsub(/(o)/, &z)
end
z = proc {|m| pp m}
hello(z)
Ich bin mir nicht bewusst einen Weg, um den Umfang eines proc on the fly zu ändern . Aber würdest du das wirklich tun wollen?
Auch in diesem Code ' 'hello'.gsub (/ (e) /) {setzt $ 1}' Proc.new vor gsub genannt wird: dies ist, wie jeder Programmiersprache Arbeit - Block wie andere das gleiche Argument ist. Es muss gebaut werden, bevor es irgendwo hinkommt. So dont Ich denke, dass Ihre Antwort etwas –
@BogdanGusiev erklärt 'Proc.new' wird aufgerufen, bevor' gsub', aber der Block nicht. Es wird nur geparst. Ein Block ist kein Argument. – sawa
Ja, wird der Block nicht vor 'in beiden Code-Varianten gsub' genannt. So ist die Differenz die Anzahl der Anrufe Block passieren zu gsub: dass 1 sein könnte oder 2. Aber es ist immer noch gleich nie 0 '$ 1 'Variable nie in dem Kontext, in der' Z' definiert ist. –