Что делает оператор * — «звездочка» в Ruby?

декабря 8, 2010  |  Published in Ruby, Основы  |  5 Comments

ruby asterisk operatorRuby — язык, который полон сюрпризов, чаще всего приятных. Одной из интересных идиом в Ruby является унарный оператор «звездочка» - *, он же asterisk и splat. К сожалению не все умеют с ним работать и не все понимают что он делает. Мне больше всего нравится название asterisk, поэтому я буду использовать его далее по тексту.

Зачем же необходим оператор asterisk? Вот несколько возможных вариантов использования осортированных по частоте применения:

1. Передача произвольного числа аргументов в метод

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

def example_method(a,b,*c,d)
  p a
  p b
  p c
  p d
end

example_method(1,2,3,4,5,6,7)
# 1
# 2
# [3,4,5,6]
# 7

В порядке следования аргументов метода им (аргументам) присваиваются значения. Как вы видите, передаваемых в метод аргументов больше, чем указано при объявлении метода. С этим в данном случае и справляется оператор asterisk, который дает понять интерпретатору Ruby, то,что все «лишние» значения необходимо поместить в массив c.

Давайте за закрепления информации рассмотрим более сложный и практичный пример: представьте, что нам необходимо составить таблицу умножения в которой неизвестное заранее количество чисел будет перемножено на числа из известного диапазона:

def mktable(f, l, *nums)
  (f..l).each {|s| nums.each {|n| printf "%4d", s*n}; puts}
end

mktable(1,5,3,4,5,8,9,56)

Здесь nums будет содержать массив [3,4,5,8,9,56].

2. Передача аргумента — массива в метод

Часто методы созданы таким образом, что не расчитаны на получение массива аргументов, что нам необходимо сделать, если мы хотим воспользоваться таким методом, но все необходимые аргументы у нас содержатся в массиве?

Можем пойти самым очевидным путем и присвоить аргументы хранящиеся в массиве переменным, которые и будут переданы методу:

our_args = [6.29, 6.3]

a = our_args[0]
b = our_args[1]

def min (a, b)
  a < b ? m = a : m = b
  puts m
end

min a, b

# а можем, используя оператор asterisk, так:

our_args = [6.29, 6.3]

def min (a, b)
a < b ? m = a : m = b
puts m
end

min *our_args

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

3. Множественное присваивание значений переменным

arr = ["Armani", "Gucci", "Celvin Klein"]
a, b = arr  # a = "Armani", b = "Gucci", а Calvin Klein куда-то пропадет...

a, *b = arr # a = "Armani", b = "Gucci" # a = "Armani", b = ["Gucci", "Calvin Klein"], Calvin Klein никуда не пропал =)

Очевидно, что если поменять a и b местами, то b будет содержать массив из первых двух элементов arr, в то время как a будет содержать последний элемент.

4. Преобразования Array в Hash и Hash в Array

Преобразование массива в хэш:

a = [:name, "Vladimir", :login, "vladimir_90", :pswd, 123456]

h = Hash[*a] #h = {:name=>"Vladimir", :login=>"vladimir_90", :pswd=>123456}

Преобразование хэша в массив:

h = {:name=>"Vladimir", :login=>"vladimir_90", :pswd=>123456}

a = [*h] #a = [[:name, "Vladimir"], [:login, "vladimir_90"], [:pswd, 123456]]

Такие преобразования бывают очень полезны, например, при парсинге xml, html, csv и других текстовых форматов данных, которые могу быть представлены в виде: ключ — значение.

Лучшая благодарность автору — ваши комментарии!

Tags:

Responses

  1. c0va23 says:

    декабря 8, 2010 at 19:42 (#)

    Первый пункт знал, а второй, третий и четвёртый нет. Спасибо!

  2. admin says:

    декабря 8, 2010 at 20:10 (#)

    c0va32, всегда пожалуйста!

  3. Scrill says:

    декабря 9, 2010 at 00:24 (#)

    В #4 a=[*h] можно заменить на тривиальное a=h.to_a, например. А так спасибо — весьма интересно.

    PS. s/Celvin/Calvin/ :)

  4. admin says:

    декабря 9, 2010 at 23:06 (#)

    Scrill, спасибо, поправил.

  5. Валентин says:

    марта 4, 2011 at 02:37 (#)

    Всё же считаю что вы должны использовать название splat, потому что оно использовано в Programming Ruby 1.9 и наиболее часто употребляется в этом значении, потому в будущем вам пригодится именно это название для данного оператора.

Leave a Response

Для подсветки кода используйте BB - коды: [language]...[/language], где language может быть: ruby, javascript, css, html.