将传递给方法的块传递给Ruby中的另一个方法

Kap*_*001 22 ruby block

我正在尝试编写ruby keep_ifdelete_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
Run Code Online (Sandbox Code Playgroud)

这有效.但我想做的事情如下:

def discard
  self - self.keep &block
end
Run Code Online (Sandbox Code Playgroud)

期望的行为:

[1, 2, 3].discard { |number| number < 2 }
# => [2, 3]
Run Code Online (Sandbox Code Playgroud)

所以我需要传递传递给discard方法的块,然后传递给keep方法.我该如何实现这一目标?

Sim*_*tti 29

您可以显式引用该块

def discard(&block)
  self - self.keep(&block)
end
Run Code Online (Sandbox Code Playgroud)

或含蓄地

def discard
  self - self.keep(&Proc.new {})
end
Run Code Online (Sandbox Code Playgroud)

在你的情况下,我会建议第一种方法.


Ric*_*nan 5

在第二个示例中,&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
Run Code Online (Sandbox Code Playgroud)

二者Proc.newproc没有块使用当前方法的块。

&proc如果discard没有得到一个块就会失败。因此,如果您想传递块或不存在块(&nil根本不传递块),则第一个示例是最好的。如果丢失的块是错误的,则第二个示例(因为我对其进行了更改)是最好的。

在这两种情况下,每次调用 'discard' 时,都会创建一个新的 'Proc' 对象,并且它不是免费的。