【问题标题】:How do I pass a statement as an argument to a block within a method?如何将语句作为参数传递给方法中的块?
【发布时间】:2012-11-16 18:00:59
【问题描述】:

我正在尝试弄清楚如何将语句作为方法参数传递 - 用作块过滤条件的一部分。例如,我有以下代码:

def method
  other_method.persons.each do |ped|

    next if ped.first_name.nil? or ped.last_name.nil?

    puts ped.id
    puts ped.full_name
  end
end

我希望能够做的事情如下(所以我可以更改方法中使用的过滤条件)。是否可以将包含块引用的语句从参数传递给块?:

def method(statement)
  other_method.persons.each do |ped|

    next if statement

    puts ped.id
    puts ped.full_name
  end
end

我很欣赏这方面的一些方向。

【问题讨论】:

    标签: ruby proc


    【解决方案1】:

    您不传递“语句”,而是传递块。通过yield 调用传递的块或捕获到proc 并使用Proc#call 调用。

    def method
      other_method.persons.each do |ped|
        next if yield(ped)
    
        puts ped.id
        puts ped.full_name
      end
    end
    
    method { |ped| ped.first_name.nil? or ped.last_name.nil? }
    

    【讨论】:

    • 这很有帮助。谢谢。
    【解决方案2】:
    Ped = Struct.new(:first_name, :last_name, :full_name, :id)
    
    # generate some test data
    peds = ['Bob', 'Hope', 'Bob Hope', 1, 'Bing', nil, 'Bing Crosby', 2, nil, 'Bacon', 'Kevin Bacon', 3].each_slice(4).map{ |x,y,z,id| Ped.new(x,y,z,id) }
    
    filter_criteria = lambda { |ped| ped.first_name.nil? or ped.last_name.nil? }
    
    peds.find_all(&filter_criteria).each { |ped| p ped }
    

    输出:

    #<struct Ped first_name="Bing", last_name=nil, full_name="Bing Crosby", id=2>
    #<struct Ped first_name=nil, last_name="Bacon", full_name="Kevin Bacon", id=3>
    

    用另一个 Proc/lambda 更改 filter_criteria 以更改过滤。另一种方法是将 find_all 包装在一个方法中以获取过滤块,如下所示:

    def filter list, &criteria
      list.find_all(&criteria)
    end
    
    filter(pedlist) { |ped| some filter criteria }.each { |ped| do something }
    

    然后可以根据需要使用生成的枚举。

    【讨论】:

    • 谢谢。这有助于我理解我的挑战。
    猜你喜欢
    • 1970-01-01
    • 2013-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-03
    • 2020-11-24
    • 2011-08-07
    • 2013-11-06
    相关资源
    最近更新 更多