Как добавить аргументы после аргументов splat в вызовы методов?

Ruby - это потрясающий язык, который меня иногда путает (так как я не такой потрясающий). И аргументы splat несут ответственность за некоторые из этих путаниц. Так просветите меня, пожалуйста.

Учитывая следующий метод:

def doSomething(with_this, *and_that)
 # ...
end

Вы можете вызвать этот метод с помощью опции 1:

doSomething("With this", "index 0", "index 1", "etc")

Или с опцией 2:

an_array = ["index 0", "index 1", "etc"]
doSomething("With this", *an_array)

Но что, если мой метод был определен следующим образом:

def doSomething(with_this, *and_that, and_even_that)
 # ...
end

Обратите внимание, что после аргумента splat существует параметр

Вопрос 1: Есть ли способ добавить аргументы для and_even_that кроме как следующим образом?

an_array = ["index 0", "index 1", "etc"]
doSomething("With this", *an_array, "With that")

В стремлении стать хорошим программистом Ruby, я также задаюсь вопросом о таких:

Дополнительные вопросы:

Лучше ли использовать более одного аргумента splat в определениях методов?

Рекомендуется ли оставлять аргументы splat для последних в определениях методов?

Заранее спасибо.

1 ответ

Вы смешиваете декларацию метода с помощью splat и вызов метода с использованием splat.

Они независимы друг от друга:

def regular_method(arg1, arg2, arg3)
 #do something
end

def method_with_splat(arg1, *more_args)
 # do something
end

arr = [1, 2, 3]

regular_method(*arr) # works!

method_with_splat(4, *arr) # works! (arg1==4, more_args==[1,2,3])

method_with_splat(4, 5, *arr) # also ok! (arg1==4, more_args==[5,1,2,3])

method_with_splat(*arr, 4, 5, 6) # just fine! (arg1==1, more_args==[2,3,4,5,6])

Итак, в том же духе:

def splat_in_the_middle(arg1, *more_args, last_arg)
 # do something
end

splat_in_the_middle(*arr, 4, 5, 6) # arg1==1, more_args==[2,3,4,5], last_arg==6

И расширяя это:

def splat_in_the_middle(arg1, *more_args, arg2, last_arg)
 # do something
end

splat_in_the_middle(*arr, 4, 5, 6) # arg1==1, more_args==[2,3,4], arg2==5, last_arg==6

Обратите внимание, что первый аргумент присваивается первому параметру, последние аргументы всегда назначаются последним параметрам, а другие становятся элементами массива more_args.

Что касается ваших дополнительных вопросов:

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

    def two_splats(arg1, *splat1, arg2, *splat2)
     # do something!
    end
    # => syntax error!
    
    two_splats(1, 2, 3, 4, 5, 6) # arg1==1, splat1==[????] arg2==?, splat2==[????]

    хотя нет проблемы с вызовом метода с более чем одним значком:

    method_with_splat(*arr, *arr) # arg1==1, more_args=[2,3,1,2,3]
  2. Если есть веские основания полагать, что ваш знак в середине, и аргументы читаемы и понятны, нет причин не помещать знак в середину. Очень полезный пример использования, например, может заключаться в том, что последним аргументом является хэш-параметры:

    def splat_in_the_middle(first_arg, *one_or_more_other_args, options)

licensed under cc by-sa 3.0 with attribution.