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?
看看有多容易认识到块实际上是一个参数?