【问题标题】:How do you use Ruby blocks to conditionally execute something?你如何使用 Ruby 块有条件地执行某些东西?
【发布时间】:2011-08-16 18:04:09
【问题描述】:

我最近购买了七周内的七种语言一书,并且一直在阅读有关 Ruby 的章节。在介绍块的部分(第 40 页)中,给出了一个代码示例,它说明了使用块来有条件地执行某事:

in_case_of_emergency do
  use_credit_card
  panic
end

def in_case_of_emergency
  yield if emergency?
end

这段代码对我来说没有多大意义,而且这本书也没有提供太多解释。我想知道你们中的一位 Ruby 大师是否会介意帮助我解决这个问题。

如何同时拥有同名的块和函数?您如何定义“紧急情况”?如果不抱怨,我什至无法在 IRB 中创建块:

NoMethodError: undefined method `in_case_of_emergency' for main:Object
    from (irb):1
    from :0

您将如何调用此代码来演示其工作原理?谢谢!

【问题讨论】:

    标签: ruby function block yield


    【解决方案1】:

    除了其他答案之外,如果您删除 yield 关键字并在方法中处理块,就像它们实际上是 Procs 一样,则可能更容易理解块。

    # for testing purposes, let's always have `emergency?` return `true`
    def emergency?
      true
    end  
    
    def in_case_of_emergency(&block)
      block.call if emergency?
    end
    
    in_case_of_emergency do
      puts "AHH! Emergency! Help!", "Seriously, I'm freaking out!"
    end
    

    看看意识到块实际上是一个参数是多么容易?

    【讨论】:

      【解决方案2】:

      首先:两者的顺序错误。你需要先定义in_case_of_emergency。

      第二:你不命名块;因此,有两个名为in_case_of_emergency 的东西是不正确的。一是函数定义,二是同一函数的调用。

      所以,一步一步:

      def emergency?
        return rand(2) == 0
      end
      

      假设您有这个函数,它随机返回一半时间true,一半时间返回false。 (男孩,这是很多紧急情况!)然后:

      def in_case_of_emergency
        yield if emergency?
      end
      

      这定义了一个名为in_case_of_emergency 的函数。调用时,它执行yield if emergency?,这是一条由条件if修改的语句yield。这是

      的语法糖
      if emergency?()
        yield
      end
      

      请注意,Ruby 函数调用不需要括号,因此我们可以删除它们;如果if 中只有一条语句,您可以将其写在与上面相同的行上(无需end)。

      接下来,我们有一个函数调用:

      in_case_of_emergency do
        use_credit_card
        panic
      end
      

      这会调用我们刚刚定义的函数in_case_of_emergency,并传递给它一个要执行的块。这两个语句(use_credit_card、panic)将由yield 执行——但前提是emergency? 的计算结果为true。

      现在这更有意义了吗?

      【讨论】:

      • 阿马丹是对的。 @Steve 你确定这本书按顺序给出了代码吗?
      • 是的,这就是书中给出的顺序。
      • 我建议换书。 =/ programmingzen.com/ruby-and-rails-recommended-books 一旦我学会了语法,我就从文档中学到了最多的东西。
      【解决方案3】:

      很简单,就是方法:

      def in_case_of_emergency 
        yield if emergency?
      end
      

      这就是对你的方法的调用:

      in_case_of_emergency do
         use_credit_card
         panic
      end 
      

      在哪里

      do
         use_credit_card
         panic
      end 
      

      是一个参数。 Ruby 方法可以隐式地将块作为参数。发生的事情是 yield 将执行您提供的块。在您的情况下,yield if emergency? 表示“如果满足条件,则执行提供的块”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多