¿Qué hace el operador (unario) * en este código Ruby?

174

Dado el código Ruby

line = "first_name=mickey;last_name=mouse;country=usa" 
record = Hash[*line.split(/=|;/)] 

Entiendo todo en la segunda línea aparte del *operador: ¿qué está haciendo y dónde está la documentación para esto? (Como puede suponer, buscar este caso está resultando difícil ...)

David Burrows
fuente

Respuestas:

271

El *es el operador splat .

Expande una Arraylista de argumentos, en este caso una lista de argumentos del Hash.[]método. (Para ser más precisos, expande cualquier objeto que responda a to_ary/ to_a, o to_aen Ruby 1.9.)

Para ilustrar, las siguientes dos afirmaciones son iguales:

method arg1, arg2, arg3
method *[arg1, arg2, arg3]

También se puede usar en un contexto diferente, para capturar todos los argumentos de método restantes en una definición de método. En ese caso, no se expande, sino que combina:

def method2(*args)  # args will hold Array of all arguments
end

Alguna información más detallada aquí .

molf
fuente
36
En general, cuando se usa como en una situación similar a LHS (cada vez que lo invoca en un valor), splat divide una matriz en valores separados, y cuando se usa en una situación similar a RHS (cada vez que lo usa en algunas variables previamente no definidas), agrupa valores separados en una matriz. Entonces a,b,*c = d,e,f,*gestablece a = d, b = e, y c = [f, g0, g1, g2, ..., gn], donde g = [g0, g1, g2, ..., gn]
rampion
2
Solo para completar, el operador de splat convierte una matriz en una lista básica de acuerdo con la terminología utilizada en 'The Well Grounded Rubyist' por David A. Black
David Burrows el
12
@ rampion: comentario maravilloso, acabas de mezclar LHS y RHS. Es al revés.
ThomasH
46

El operador splat desempaqueta un conjunto pasado a una función para que cada elemento se envíe a la función como un parámetro individual.

Un simple ejemplo:

>> def func(a, b, c)
>>   puts a, b, c
>> end
=> nil

>> func(1, 2, 3)  #we can call func with three parameters
1
2
3
=> nil

>> list = [1, 2, 3]
=> [1, 2, 3]

>> func(list) #We CAN'T call func with an array, even though it has three objects
ArgumentError: wrong number of arguments (1 for 3)
    from (irb):12:in 'func'
    from (irb):12

>> func(*list) #But we CAN call func with an unpacked array.
1
2
3
=> nil

¡Eso es!

BJ Homer
fuente
6

Como todos mencionan, es un "splat". Buscar la sintaxis de Ruby es imposible, y lo he hecho en otras preguntas. La respuesta a esa parte de la pregunta es que buscas en

asterisk in ruby syntax

en Google. Google está ahí para ti, solo pon lo que ves en palabras.

De todos modos, como muchos códigos Ruby, ese código es bastante denso. los

line.split(/=|;/)

hace que un conjunto de elementos seis, first_name, mickey, last_name, mouse, country, usa. Luego, el splat se usa para convertirlo en un Hash. Ahora la gente de Ruby siempre te envía a mirar el método Splat, ya que todo está expuesto en Ruby. No tengo idea de dónde está, pero una vez que tenga eso, verá que se ejecuta a fortravés de la matriz y crea el hash.

Buscaría el código en la documentación principal . Si no puede encontrarlo (no pude), intente escribir un código como este (que funciona, pero NO es un código similar a Ruby):

line = "first_name=mickey;last_name=mouse;country=usa"
presplat = line.split(/=|;/)
splat = Hash.new
for i in (0..presplat.length-1)
    splat[presplat[i]] = presplat[i+1] if i%2==0
end

puts splat["first_name"]

y luego la pandilla Ruby podrá decirte por qué tu código es tonto, malo o simplemente incorrecto.

Si ha leído hasta aquí, lea la documentación de Hash para la inicialización.

Básicamente, un hash que se inicializa con varios argumentos los crea como pares de valores clave:

Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}

Entonces, en su ejemplo, esto conduciría al siguiente Hash:

{"first_name"=>"mickey", "last_name"=>"mouse", "county"=>"usa"}
Dan Rosenstark
fuente