Что делает (унарный) оператор * в этом коде Ruby?

174

Учитывая код Ruby

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

Я все понимаю во второй строке, кроме *оператора - что он делает и где документация для этого? (как вы можете догадаться, поиск этого дела оказывается трудным ...)

Дэвид Берроуз
источник

Ответы:

271

*Является знак оператора.

Он расширяет Arrayсписок аргументов, в данном случае список аргументов Hash.[]метода. (Точнее, он раскрывает любой объект, который отвечает на to_ary/ to_aили to_aв Ruby 1.9.)

Для иллюстрации, следующие два утверждения равны:

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

Его также можно использовать в другом контексте, чтобы перехватить все оставшиеся аргументы метода в определении метода. В этом случае он не расширяется, а объединяет:

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

Более подробная информация здесь .

Molf
источник
36
В общем случае, когда используется как в LHS-подобной ситуации (каждый раз, когда вы вызываете его для значения), splat разбивает массив на отдельные значения, а при использовании в RHS-подобной ситуации (в любое время, когда вы его используете). для некоторых ранее неопределенных переменных) он группирует отдельные значения в массив. Поэтому a,b,*c = d,e,f,*gустанавливает a = d, b = e и c = [f, g0, g1, g2, ..., gn], где g = [g0, g1, g2, ..., gn]
rampion
2
Просто для полноты, оператор splat превращает массив в пустой список в соответствии с терминологией, использованной в «Хорошо заземленном Rubyist» Дэвида А. Блэка
David Burrows
12
@rampion: Замечательный комментарий, вы только что смешали LHS и RHS. Это наоборот.
ThomasH
47

Оператор splat распаковывает массив, переданный функции, так что каждый элемент отправляется в функцию как отдельный параметр.

Простой пример:

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

Это оно!

Би Джей Гомер
источник
6

Как все говорят, это «сплат». Искать синтаксис Ruby невозможно, и я задавал это в других вопросах. Ответ на эту часть вопроса заключается в том, что вы ищете

asterisk in ruby syntax

в гугле. Google для вас, просто поместите то, что вы видите, в слова.

В любом случае, как много кода на Ruby, этот код довольно плотный.

line.split(/=|;/)

делает массив элементов SIX, first_name, mickey, last_name, mouse, country, usa. Затем сплат используется для преобразования в хэш. Теперь люди из Ruby всегда посылают вас посмотреть на метод Splat, поскольку в Ruby все открыто. Я понятия не имею, где это, но как только вы это сделаете, вы увидите, что он запускает forмассив и создает хэш.

Вы бы искали код в основной документации. Если вы не можете найти его (я не смог), вы попытаетесь написать такой код (который работает, но НЕ похож на 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"]

и тогда банда Ruby сможет сказать вам, почему ваш код глупый, плохой или просто неправильный.

Если вы прочитали это далеко, прочитайте Хэш документацию по для инициализации.

По сути, хеш, который инициализируется несколькими аргументами, создает их как пары ключ-значение:

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

Так что в вашем примере это приведет к следующему хешу:

{"first_name"=>"mickey", "last_name"=>"mouse", "county"=>"usa"}
Дэн Розенстарк
источник