La mayoría son conscientes del _
significado especial de 'en IRB como tenedor del último valor de retorno, pero eso no es lo que estoy preguntando aquí.
En cambio, estoy preguntando sobre _
cuándo se usa como nombre de variable en código Ruby simple y antiguo. Aquí parece tener un comportamiento especial, similar a una “variable no importa” (à la Prolog ). A continuación, se muestran algunos ejemplos útiles que ilustran su comportamiento único:
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
Todos estos se ejecutaron en Ruby directamente (con puts
s agregados), no en IRB, para evitar conflictos con su funcionalidad adicional.
Sin embargo, todo esto es el resultado de mi propia experimentación, ya que no puedo encontrar ninguna documentación sobre este comportamiento en ninguna parte (es cierto que no es lo más fácil de buscar). En última instancia, tengo curiosidad por saber cómo funciona todo esto internamente para poder comprender mejor exactamente de qué se trata _
. Así que estoy pidiendo referencias a la documentación y, preferiblemente, el código fuente de Ruby (y quizás RubySpec ) que revele cómo se _
comporta en Ruby.
Nota: la mayor parte de esto surgió de esta discusión con @Niklas B.
lambda { |_, _| _ }.call(4, 2)
entre 1.8 y 1.9 es solo un efecto secundario involuntario, entonces. Como en circunstancias "normales" en las que el nombre de la variable no se puede duplicar, el orden en el que se asignan es intrascendente.|_,_,...|
porque se ha suprimido el error duplicado._
es un identificador válido. Los identificadores no solo pueden contener guiones bajos, también pueden ser un guión bajo._ = o = Object.new _.object_id == o.object_id # => true
También puede usarlo como nombres de métodos:
def o._; :_ end o._ # => :_
Por supuesto, no es exactamente un nombre legible, ni pasa ninguna información al lector sobre a qué se refiere la variable o qué hace el método.
IRB
, en particular, establece_
el valor de la última expresión:$ irb > 'asd' # => "asd" > _ # => "asd"
Como está en el código fuente , simplemente se establece
_
en el último valor:@workspace.evaluate self, "_ = IRB.CurrentContext.last_value"
Hice un poco de exploración del repositorio. Esto es lo que encontré:
En las últimas líneas del archivo
id.c
, está la llamada:REGISTER_SYMID(idUScore, "_");
grep
La fuente deidUScore
me dio dos resultados aparentemente relevantes:shadowing_lvar_gen
funciónwarn_unused_var
funciónshadowing_lvar_gen
parece ser el mecanismo mediante el cual el parámetro formal de un bloque reemplaza a una variable del mismo nombre que existe en otro ámbito. Es la función que parece generar "nombre de argumento duplicado"SyntaxError
y la advertencia "sombreado de variable local externa".Después
grep
de buscar la fuenteshadowing_lvar_gen
, encontré lo siguiente en el registro de cambios de Ruby 1.9.3 :Cuál es probablemente el origen de esta línea :
if (idUScore == name) return name;
De esto, deduzco que en una situación como
proc { |_, _| :x }.call :a, :b
, una_
variable simplemente ensombrece a la otra.Aquí está el compromiso en cuestión . Básicamente introdujo estas dos líneas:
if (!uscore) uscore = rb_intern("_"); if (uscore == name) return;
De una época en la
idUScore
que ni siquiera existía, al parecer.fuente
lambda { |_, _| 42 }
funciona mientraslambda { |x, x| 42 }
que no.|_, _|
funciona, pero|__, __|
no._
parece tener un significado especial, veré si puedo extraer alguna información de la fuente Ruby.