Co robi (jednoargumentowy) operator * w tym kodzie Ruby?

174

Biorąc pod uwagę kod Ruby

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

Rozumiem wszystko w drugiej linii oprócz *operatora - co robi i gdzie jest do tego dokumentacja? (jak można się domyślić, szukanie tego przypadku okazuje się trudne ...)

David Burrows
źródło

Odpowiedzi:

271

*Jest ikona operatora.

Rozwija an Arraydo listy argumentów, w tym przypadku listy argumentów Hash.[]metody. (Mówiąc dokładniej, rozwija każdy obiekt, który reaguje na to_ary/ to_alub to_aw Rubim 1.9.)

Aby to zilustrować, poniższe dwa stwierdzenia są równe:

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

Może być również używany w innym kontekście, aby przechwycić wszystkie pozostałe argumenty metody w definicji metody. W takim przypadku nie rozszerza się, ale łączy:

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

Więcej szczegółowych informacji tutaj .

molf
źródło
36
Ogólnie rzecz biorąc, gdy jest używany jak w sytuacji podobnej do LHS (za każdym razem, gdy wywołujesz ją na wartości), splat dzieli tablicę na oddzielne wartości, a gdy jest używany w sytuacji podobnej do RHS (za każdym razem, gdy jej używasz na niektórych wcześniej niezdefiniowanych zmiennych), grupuje oddzielne wartości w tablicę. Więc a,b,*c = d,e,f,*gustawia a = d, b = e, ic = [f, g0, g1, g2, ..., gn], gdzie g = [g0, g1, g2, ..., gn]
rampion
2
Aby uzyskać kompletność, operator splat zamienia tablicę w pustą listę zgodnie z terminologią używaną w „The Well Grounded Rubyist” Davida A. Blacka
David Burrows
12
@rampion: Cudowny komentarz, właśnie wymieszałeś LHS i RHS. Jest odwrotnie.
ThomasH,
46

Operator splat rozpakowuje tablicę przekazaną do funkcji, dzięki czemu każdy element jest wysyłany do funkcji jako indywidualny parametr.

Prosty przykład:

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

Otóż ​​to!

BJ Homer
źródło
6

Jak wszyscy wspominają, jest to „plama”. Poszukiwanie składni Ruby jest niemożliwe i zadałem to w innych pytaniach. Odpowiedź na tę część pytania jest taka, że ​​szukasz

asterisk in ruby syntax

w Google. Google jest do Twojej dyspozycji, po prostu opisz to, co widzisz, w słowach.

W każdym razie, podobnie jak większość kodu Rubiego, ten kod jest dość gęsty. Plik

line.split(/=|;/)

sprawia szereg elementów sześć, first_name, mickey, last_name, mouse, country, usa. Następnie ikona jest używana do przekształcenia tego w skrót. Teraz ludzie Ruby zawsze wysyłają cię do metody Splat, ponieważ wszystko jest ujawnione w Rubim. Nie mam pojęcia, gdzie to jest, ale kiedy już to zrobisz, zobaczysz, że przechodzi forprzez tablicę i buduje hash.

Szukałbyś kodu w podstawowej dokumentacji. Jeśli nie możesz go znaleźć (nie mogłem), spróbuj napisać taki kod (który działa, ale NIE jest kodem podobnym do Rubiego):

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

a wtedy gang Rubiego będzie w stanie powiedzieć ci, dlaczego twój kod jest głupi, zły lub po prostu błędny.

Jeśli przeczytałeś do tej pory, przeczytaj dokumentację Hash dotyczącą inicjalizacji.

Zasadniczo skrót, który jest inicjowany kilkoma argumentami, tworzy je jako pary klucz-wartość:

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

W twoim przykładzie doprowadziłoby to do następującego skrótu:

{"first_name"=>"mickey", "last_name"=>"mouse", "county"=>"usa"}
Dan Rosenstark
źródło