O que o operador (unário) * faz nesse código Ruby?

174

Dado o código Ruby

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

Entendo tudo na segunda linha além do *operador - o que está fazendo e onde está a documentação para isso? (como você pode imaginar, procurar este caso está se mostrando difícil ...)

David Burrows
fonte

Respostas:

271

O *é o operador splat .

Ele expande um Arraypara uma lista de argumentos, nesse caso, uma lista de argumentos para o Hash.[]método. (Para ser mais preciso, ele expande qualquer objeto que responda a to_ary/ to_aou to_ano Ruby 1.9.)

Para ilustrar, as duas instruções a seguir são iguais:

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

Também pode ser usado em um contexto diferente, para capturar todos os argumentos restantes do método em uma definição de método. Nesse caso, ele não se expande, mas combina:

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

Algumas informações mais detalhadas aqui .

molf
fonte
36
Em geral, quando usado como em uma situação semelhante ao LHS (sempre que você o invoca em um valor), splat divide uma matriz em valores separados e quando usado em uma situação semelhante ao RHS (sempre que você o usa em algumas variáveis ​​indefinidas anteriormente), agrupa valores separados em uma matriz. Portanto, a,b,*c = d,e,f,*gdefine a = d, b = e ec = [f, g0, g1, g2, ..., gn], onde g = [g0, g1, g2, ..., gn]
rampion
2
Apenas para completar, o operador splat transforma um array em uma lista nua de acordo com a terminologia utilizada no 'The Rubyist bem fundamentada' por David A. Black
David Burrows
12
@rampion: Comentário maravilhoso, você acabou de misturar LHS e RHS. É o contrário.
ThomasH
46

O operador splat descompacta uma matriz passada para uma função, para que cada elemento seja enviado à função como um parâmetro individual.

Um exemplo simples:

>> 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

É isso aí!

BJ Homer
fonte
6

Como todo mundo menciona, é um "splat". Procurar a sintaxe do Ruby é impossível, e eu fiz isso em outras perguntas. A resposta para essa parte da pergunta é que você pesquisa no

asterisk in ruby syntax

no Google. O Google está aí para você, basta colocar o que vê em palavras.

De qualquer forma, como muitos códigos Ruby, esse código é bastante denso. o

line.split(/=|;/)

cria uma matriz de seis elementos first_name, mickey, last_name, mouse, country, usa,. Em seguida, o splat é usado para transformar isso em um hash. Agora, o pessoal do Ruby sempre o envia para examinar o método Splat, pois tudo é exposto no Ruby. Eu não tenho idéia de onde está, mas depois que você tiver isso, verá que ele executa um foratravés da matriz e cria o hash.

Você procuraria o código na documentação principal . Se você não conseguir encontrá-lo (não consegui), tente escrever um código como este (que funciona, mas NÃO é um código semelhante ao 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"]

e então a turma do Ruby poderá lhe dizer por que seu código é bobo, ruim ou simplesmente errado.

Se você leu até aqui, leia a documentação do Hash para inicialização.

Basicamente, um hash inicializado com vários argumentos os cria como pares de valores-chave:

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

Portanto, no seu exemplo, isso levaria ao seguinte Hash:

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