|| = es una expresión común de Ruby: asigna el valor solo si no está ya configurado. El efecto es el mismo que el código como
if some_variable == nil
some_variable = some_value
end
o
some_variable= some_value unless some_variable
===, cuando no anulado, compara dos objetos de la identidad. En el caso de Hash === args.last
, Hash (que es un objeto de tipo Clase) está comprobando si coincide con la clase del último elemento en Array Array. El código está haciendo uso del hecho aparente de que la implementación de Class # === obliga a controlar la clase del objeto comparado.
No funciona al revés, por ejemplo:
a = [{}]
Hash === a.last #=> true
a.last === Hash #=> false
Los argumentos de cola a un método se pueden suministrar como el contenido de un hash sin necesidad de proporcionar la {}
Entonces puede hacer esto:
def hello(arg1, arg2, arg3)
puts [arg1.class, arg2.class, arg3.class].join(',')
end
hello 1,2,3 #=> Fixnum,Fixnum,Fixnum
hello :a, "b", :c => 1, :d => 99 #=> Symbol,String,Hash
A menudo se utiliza para proporcionar una lista de longitud variable de parámetros opcionales para la función.
¿Estás seguro de que transcribiste el código original con precisión, por cierto? Para obtener una matriz de argumentos, normalmente agregaría un * al argumento como declarado, de lo contrario args tendría que ingresarse como una matriz, que preferiría derrotar al objeto.
def add_spec_path_to(*args) # now args is an array
args << {} unless Hash === args.last # if trailing arguments cannot be
# interpreted as a Hash, add an empty
# Hash here so that following code will
# not fail
args.last[:spec_path] ||= caller(0)[2] # Set the spec_path option if it's not
# already set
end
EDIT: Ampliando aún más en la cosa * args, intente esto:
def x(*args)
puts args.join(',')
puts args.map{|a| a.class }.join(',')
end
x 1,2,:a=>5,:b=>6
1,2,a5b6
Fixnum,Fixnum,Hash
... usando args * Causas argumentos que se presentarán al método como una matriz. Si yo no uso el *, de esta manera, por ejemplo:
def y(args)
puts args.join(',')
puts args.map{|a| a.class }.join(',')
end
... entonces args tiene que ser una matriz antes de que llame al método, o voy a conseguir un "ArgumentError: número incorrecto de argumentos "para todo menos una cosa aprobada". Por lo tanto, debe verse así:
y [1,2,{:c=>3,:d=>4}]
... con el hash creado explícitamente con {}. Y es feo
Todo lo anterior probado con MRI 1.8.6, por cierto.
No, pasando de una matriz tiene sentido, ya que no se devuelve argumentos, por lo contrario, un hash anexado se perdería. – rampion
No estoy seguro de entender: llamarías al método así: some_method ([arg1, arg2, arg3], options_hash)? Eso es horrible: vea la respuesta editada arriba ... –
Gran explicación, Mike. –