Ответ 1
Вы можете явно ссылаться на блок
def discard(&block)
self - self.keep(&block)
end
или неявно
def discard
self - self.keep(&Proc.new {})
end
В вашем случае я бы предложил первый подход.
Я пытаюсь написать клон методов массива ruby keep_if
и delete_if
. Вот мой код.
module Strain
def keep
self.inject([]) do |extracts, element|
yield(element) ? extracts << element : extracts
end
end
def discard
self.inject([]) do |extracts, element|
!yield(element) ? extracts << element : extracts
end
end
end
class Array
include Strain
end
Это работает. Но я хочу сделать что-то вроде:
def discard
self - self.keep &block
end
Желаемое поведение:
[1, 2, 3].discard { |number| number < 2 }
# => [2, 3]
Поэтому мне нужно передать блок, который передается методу discard
, который будет передан методу keep
. Как достичь этого?
Вы можете явно ссылаться на блок
def discard(&block)
self - self.keep(&block)
end
или неявно
def discard
self - self.keep(&Proc.new {})
end
В вашем случае я бы предложил первый подход.
Во втором примере &Proc.new {}
не пропускает блок, он создает новый пустой. Следует опустить {}
и написать его как self.keep(&Proc.new)
или просто keep(&proc)
, так как self.
является избыточным, а proc
является рекомендуемым синонимом для Proc.new
:
# passes on the block or the absence of a block
def discard(&block)
self - keep(&block)
end
# passes on the block and fails if no block given
def discard
self - keep(&proc)
end
И Proc.new
, и proc
без блока используют блок текущего метода.
&proc
потерпит неудачу, если discard
не получит блок. Поэтому первый пример является лучшим, если вы хотите пропустить блок или отсутствие блока (&nil
вообще не пропускает блок). Второй пример (как я его изменил) является лучшим, если отсутствующий блок является ошибкой.
В обоих случаях каждый раз, когда вызывается метод discard, создается новый объект Proc, который не является бесплатным.