你如何使用Ruby块来有条件地执行某些操作?

时间:2022-04-07 23:29:02

I recently purchased the book Seven Languages in Seven Weeks and have been reading through the chapter on Ruby. In the section which introduces blocks (page 40), a code sample is given which illustrates the use of blocks for the purpose of conditionally executing something:

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

in_case_of_emergency do
  use_credit_card
  panic
end

def in_case_of_emergency
  yield if emergency?
end

This code doesn't make much sense to me, and the book doesn't provide much of an explanation. I was wondering if one of you Ruby gurus would mind helping me get my head around this one.

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

How can you have both a block and a function with the same name? How would you define "emergency?" I can't even create the block in IRB without it complaining:

你怎么能同时拥有一个块和一个同名的函数?你怎么定义“紧急情况?”如果没有抱怨,我甚至无法在IRB中创建块:

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

And how would you invoke this code to demonstrate how it works? Thanks!

您将如何调用此代码来演示它是如何工作的?谢谢!

3 个解决方案

#1


10  

First off: the two are in the wrong order. You need to define in_case_of_emergency first.

首先:两个订单错误。您需要先定义in_case_of_emergency。

Second: You don't name blocks; therefore, it is incorrect that there are two things named in_case_of_emergency. One is a function definition, while the second is the function invocation of that same function.

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

So, step-by-step:

所以,一步一步:

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

Let's say you have this function that returns true half the time, and false half the time, randomly. (Boy, that's a lot of emergencies!) Then:

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

def in_case_of_emergency
  yield if emergency?
end

This defines a function named in_case_of_emergency. When called, it executes yield if emergency?, which is a statement yield modified by the conditional if. This is syntactic sugar for

这定义了一个名为in_case_of_emergency的函数。当被调用时,它会执行yield,如果紧急?,这是由条件if修改的语句产量。这是语法糖

if emergency?()
  yield
end

Note that Ruby does not require brackets for function invocation, thus we can drop them; and if there is only one statement inside an if, you can write it on the same line as above (obviating the need for an end).

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

Next, we have a function invocation:

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

in_case_of_emergency do
  use_credit_card
  panic
end

This calls the function we just defined, in_case_of_emergency, passing it a block to execute. These are the two statements (use_credit_card, panic) that would be executed by yield - but only if the emergency? evaluates to true.

这会调用我们刚刚定义的函数in_case_of_emergency,将一个块传递给它来执行。这些是将由yield执行的两个语句(use_credit_card,panic) - 但仅在紧急情况下?评估为真。

Does this make more sense now?

这现在更有意义了吗?

#2


2  

that's simple, that is the method:

这很简单,就是方法:

def in_case_of_emergency 
  yield if emergency?
end

and that is the call to your method:

这是对你的方法的调用:

in_case_of_emergency do
   use_credit_card
   panic
end 

wheres

哪里

do
   use_credit_card
   panic
end 

is an argument. Ruby methods can implicitly take blocks as arguments. What happens is that yield will execute the block you provided. In your case yield if emergency? means "execute provided block if conditions are met".

是一个论点。 Ruby方法可以隐式地将块作为参数。会发生什么是yield会执行您提供的块。在你的情况下,如果紧急收益?表示“满足条件时执行提供的块”。

#3


0  

Adding to other answers, it may be easier to understand blocks if you drop the yield keyword and treat blocks in methods like the Procs they actually are.

添加到其他答案中,如果删除yield关键字并在诸如实际上的Proc之类的方法中处理块,则可能更容易理解块。

# 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

See how much easier it is to realize that the block is actually an argument?

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

#1


10  

First off: the two are in the wrong order. You need to define in_case_of_emergency first.

首先:两个订单错误。您需要先定义in_case_of_emergency。

Second: You don't name blocks; therefore, it is incorrect that there are two things named in_case_of_emergency. One is a function definition, while the second is the function invocation of that same function.

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

So, step-by-step:

所以,一步一步:

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

Let's say you have this function that returns true half the time, and false half the time, randomly. (Boy, that's a lot of emergencies!) Then:

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

def in_case_of_emergency
  yield if emergency?
end

This defines a function named in_case_of_emergency. When called, it executes yield if emergency?, which is a statement yield modified by the conditional if. This is syntactic sugar for

这定义了一个名为in_case_of_emergency的函数。当被调用时,它会执行yield,如果紧急?,这是由条件if修改的语句产量。这是语法糖

if emergency?()
  yield
end

Note that Ruby does not require brackets for function invocation, thus we can drop them; and if there is only one statement inside an if, you can write it on the same line as above (obviating the need for an end).

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

Next, we have a function invocation:

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

in_case_of_emergency do
  use_credit_card
  panic
end

This calls the function we just defined, in_case_of_emergency, passing it a block to execute. These are the two statements (use_credit_card, panic) that would be executed by yield - but only if the emergency? evaluates to true.

这会调用我们刚刚定义的函数in_case_of_emergency,将一个块传递给它来执行。这些是将由yield执行的两个语句(use_credit_card,panic) - 但仅在紧急情况下?评估为真。

Does this make more sense now?

这现在更有意义了吗?

#2


2  

that's simple, that is the method:

这很简单,就是方法:

def in_case_of_emergency 
  yield if emergency?
end

and that is the call to your method:

这是对你的方法的调用:

in_case_of_emergency do
   use_credit_card
   panic
end 

wheres

哪里

do
   use_credit_card
   panic
end 

is an argument. Ruby methods can implicitly take blocks as arguments. What happens is that yield will execute the block you provided. In your case yield if emergency? means "execute provided block if conditions are met".

是一个论点。 Ruby方法可以隐式地将块作为参数。会发生什么是yield会执行您提供的块。在你的情况下,如果紧急收益?表示“满足条件时执行提供的块”。

#3


0  

Adding to other answers, it may be easier to understand blocks if you drop the yield keyword and treat blocks in methods like the Procs they actually are.

添加到其他答案中,如果删除yield关键字并在诸如实际上的Proc之类的方法中处理块,则可能更容易理解块。

# 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

See how much easier it is to realize that the block is actually an argument?

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