Die meisten sind sich dessen bewusst _
ist eine besondere Bedeutung in IRB als Halter für letzten Rückgabewert, aber das ist nicht was ich hier zu fragen.
Stattdessen frage ich nach, _
wann sie als Variablenname in normalem Ruby-Code verwendet werden. Hier scheint es ein besonderes Verhalten zu haben, ähnlich einer „egal Variablen“ (à la Prolog ). Hier sind einige nützliche Beispiele, die das einzigartige Verhalten veranschaulichen:
lambda { |x, x| 42 } # SyntaxError: duplicated argument name
lambda { |_, _| 42 }.call(4, 2) # => 42
lambda { |_, _| 42 }.call(_, _) # NameError: undefined local variable or method `_'
lambda { |_| _ + 1 }.call(42) # => 43
lambda { |_, _| _ }.call(4, 2) # 1.8.7: => 2
# 1.9.3: => 4
_ = 42
_ * 100 # => 4200
_, _ = 4, 2; _ # => 2
Diese wurden alle direkt in Ruby ausgeführt (mit puts
s hinzugefügt) - nicht IRB -, um Konflikte mit der zusätzlichen Funktionalität zu vermeiden.
Dies ist alles ein Ergebnis meiner eigenen Experimente, da ich nirgendwo eine Dokumentation zu diesem Verhalten finden kann (zugegebenermaßen ist es nicht die einfachste Sache, danach zu suchen). Letztendlich bin ich gespannt, wie das alles intern funktioniert, damit ich besser verstehen kann, woran es besonders ist _
. Daher bitte ich um Verweise auf die Dokumentation und vorzugsweise auf den Ruby-Quellcode (und möglicherweise RubySpec ), die zeigen, wie _
sich Ruby verhält.
Hinweis: Das meiste davon entstand aus dieser Diskussion mit @Niklas B.
lambda { |_, _| _ }.call(4, 2)
zwischen 1,8 und 1,9 dann nur eine unbeabsichtigte Nebenwirkung ist. Wie unter "normalen" Umständen, unter denen der Variablenname nicht dupliziert werden kann, spielt die Reihenfolge, in der sie zugewiesen werden, keine Rolle.|_,_,...|
dass der Duplikatfehler unterdrückt wurde._
ist eine gültige Kennung. Bezeichner können nicht nur Unterstrichen enthalten, können sie auch sein ein Unterstrich._ = o = Object.new _.object_id == o.object_id # => true
Sie können es auch als Methodennamen verwenden:
def o._; :_ end o._ # => :_
Natürlich ist es weder ein lesbarer Name, noch gibt es dem Leser Informationen darüber, worauf sich die Variable bezieht oder was die Methode tut.
IRB
setzt insbesondere_
auf den Wert des letzten Ausdrucks:$ irb > 'asd' # => "asd" > _ # => "asd"
Wie im Quellcode wird einfach
_
der letzte Wert festgelegt:@workspace.evaluate self, "_ = IRB.CurrentContext.last_value"
Habe ein Repository erkundet. Folgendes habe ich gefunden:
In den letzten Zeilen der Datei
id.c
steht der Aufruf:REGISTER_SYMID(idUScore, "_");
grep
Die Quelle füridUScore
gab mir zwei scheinbar relevante Ergebnisse:shadowing_lvar_gen
Funktionwarn_unused_var
Funktionshadowing_lvar_gen
scheint der Mechanismus zu sein, durch den der formale Parameter eines Blocks eine gleichnamige Variable ersetzt, die in einem anderen Bereich existiert. Es ist die Funktion, die den Namen "duplizierter Argumentname"SyntaxError
und die Warnung "äußere lokale Variable beschatten" auszulösen scheint .Nachdem ich
grep
die Quelle für gefunden hatteshadowing_lvar_gen
, fand ich im Änderungsprotokoll für Ruby 1.9.3 Folgendes :Welches ist wahrscheinlich der Ursprung dieser Linie :
if (idUScore == name) return name;
Daraus schließe ich, dass in einer Situation wie
proc { |_, _| :x }.call :a, :b
einer eine_
Variable einfach die andere beschattet.Hier ist das fragliche Commit . Grundsätzlich wurden diese beiden Zeilen eingeführt:
if (!uscore) uscore = rb_intern("_"); if (uscore == name) return;
Aus einer Zeit, als
idUScore
es anscheinend gar nicht gab.quelle
lambda { |_, _| 42 }
funktioniert , währendlambda { |x, x| 42 }
dies nicht tut.|_, _|
funktioniert, aber|__, __|
nicht._
scheint eine besondere Bedeutung zu haben, ich werde sehen, ob ich irgendwelche Informationen aus der Ruby-Quelle graben kann.