Что означает символ * (звездочка) рядом с аргументом функции и как использовать это в других сценариях?

Я использую Ruby on Rails 3, и я хотел бы знать, что означает наличие оператора * рядом с аргументом функции и для понимания его использования в других сценариях.

Пример сценария (этот метод был из структуры Ruby on Rails 3):

def find(*args)
  return to_a.find { |*block_args| yield(*block_args) } if block_given?

  options = args.extract_options!

  if options.present?
    apply_finder_options(options).find(*args)
  else
    case args.first
    when :first, :last, :all
      send(args.first)
    else
      find_with_ids(*args)
    end
  end
end

Ответ 1

Это оператор splat, который исходит от ruby ​​(и, следовательно, не является специфичным для рельсов). Его можно применять двумя способами в зависимости от того, где он используется:

  • чтобы "упаковать" ряд аргументов в массив
  • для разделения массива на список аргументов

В вашей функции вы видите оператор splat, используемый в определении функции. В результате функция принимает любое количество аргументов. Полный список аргументов будет помещен в args как массив.

def foo(*args)
  args.each_with_index{ |arg, i| puts "#{i+1}. #{arg}" }
end

foo("a", "b", "c")
# 1. a   <== this is the output
# 2. b
# 3. c

Второй вариант был бы, если вы рассмотрите следующий метод:

def bar(a, b, c)
  a + b + c
end

Для этого требуется ровно три аргумента. Вы можете вызвать этот метод следующим образом

my_array = [1, 2, 3]
bar(*my_array)
# returns 6

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

foo(*my_array)
# 1. 1   <== this is the output
# 2. 2
# 3. 3

Как вы можете видеть в методе вашего примера, эти правила одинаково применимы к параметрам блока.

Ответ 2

Это аргумент splat, который в основном означает, что любые "дополнительные" аргументы, переданные методу, будут присваиваться * args.