#ruby
#рубиновый #ruby
Вопрос:
Я хотел бы создать метод, который принимает аргумент блока, но по умолчанию для блока используется метод, который всегда возвращает true .
def my_method(amp;print_if = Proc.new { true })
internal_value = [1, 2, 3]
puts "printing" if print_if.call(internal_value)
end
my_method { |array| array[1] == 2 }
"printing"
=> nil
my_method { |array| array[1] == 3 }
=> nil
my_method
"printing"
=> nil
Кажется, что мой лучший вариант — проверить наличие блока в методе. Это работает, это просто неуклюже
def my_method(amp;print_if)
internal_value = [1, 2, 3]
puts "printing" if !block_given? || print_if.call(internal_value)
end
my_method { |array| array[1] == 2 }
"printing"
=> nil
my_method { |array| array[1] == 3 }
=> nil
my_method
"printing"
=> nil
Есть ли способ установить аргумент блока по умолчанию в Ruby? Пожалуйста, никаких ответов, которые полагаются на внешние библиотеки (даже Rails), просто пытаюсь выяснить, возможно ли это с помощью чистого Ruby.
Комментарии:
1. Вы также можете сделать (со своим вторым) примером
print_if ||= -> { true }
2. Я только что заметил ваш второй блок кода после публикации моего ответа (с момента удаления), но в этом нет ничего плохого, поскольку код прекрасно описывает то, чего вы пытаетесь достичь. Я лично считаю
print_if.nil? ? true : print_if.call(internal_value)
, что читается лучше.3. @Sergio, о чем ты говоришь?
4. Помните, что объявление блока в качестве аргумента влечет за собой довольно значительное снижение производительности, поскольку Ruby необходимо собирать много контекстной информации для блока, который может быть передан. По возможности используйте
block_given?
иyield
в сочетании. Для легкого использования разница в основном академическая, но для кода, чувствительного к производительности, разница может быть существенной. Общее правило заключается в том, чтобы объявлять параметры блока только в том случае, если вам нужно переслать блок другому методу, и в этом случае вам все равно придется заплатить цену.
Ответ №1:
Вы можете использовать этот грязный хак:
def my_method(print_if = -> (*args) { block_given? ? yield(*args) : true })
internal_value = [1, 2, 3]
puts "printing" if print_if.call(internal_value)
end
Но удобно ли это?
Комментарии:
1. Я думаю, что этот ответ довольно хорош в том смысле, что он доказывает, что в Ruby нет хорошего способа установки значений по умолчанию для аргументов, которые должны быть procs / lambdas / blocks . Я вообще не самый большой поклонник того, как Ruby позволяет передавать методы, но такова жизнь. Просто хотел посмотреть, есть ли ярлык, который я пропустил.