Ruby 简单程序跟踪(产量 - 方法)



这是我根据TeamTreeHouse上Ruby轨道上的Ruby块的视频课程创建的代码,这是代码及其输出。

我的代码:

def get_name(prompt, &block)
print prompt + ": "
name = gets.chomp
print "age: "
age = gets.chomp
#block.call(nam,ag)
yield name, age
yield age
name
end
my_name = get_name("enter your name") do |name, age|
puts "That's a cool name, #{name}, #{age}"
end
my_name2 = get_name("enter your age") do |age|
puts "That's a cool age, #{age}"
end
puts "my_name: #{my_name} #{my_name2}"

我的输出:

treehouse:~/workspace$ ruby calling_blocks.rb                                                                             
enter your name: ahmed                                                                                                    
age: 25                                                                                                                   
That's a cool name, ahmed, 25                                                                                             
That's a cool name, 25,                                                                                                   
enter your age: 25                                                                                                        
age: 25                                                                                                                   
That's a cool age, 25                                                                                                     
That's a cool age, 25                                                                                                     
my_name: ahmed 25

该代码的问题在于,在跟踪它时,我发现输出无关紧要,我认为必须发生以下情况:

1-第一个get_name块发送了一个带有问题"输入您的名字"的提示,然后该方法get_name首先打印短语"输入您的名字",该短语作为称为提示的参数,然后该方法将名称作为输入并将年龄作为输入

2-第一个收益"yield名称,年龄"发送回第一个get_name块的名称和年龄,通过|name,age|在块中接收,然后它们都显示在

puts "That's a cool name, #{name}, #{age}" 

作为这个

That's a cool name, ahmed, 25 

3-第二个收益"yield age"这次只发送回第一个get_name块的age,它通过|name,age|在块中接收,这次由于我们只发送回块一个参数,而块有两个参数,这次块上的name参数接收到来自"yield name"的age参数, 虽然块上的 age 参数没有收到任何内容,所以在块中,#{name} 只显示值,而 #{age} 不显示任何值

puts "That's a cool name, #{name}, #{age}" 

作为这个

That's a cool name, 25,

我的追踪是真的吗? 因为如果这是真的,为什么在第二个get_name块中,这是

my_name2 = get_name("enter your age") do |age|
puts "That's a cool age, #{age}"
end

输出为:

That's a cool age, 25                                                                                                     
That's a cool age, 25  

而不是:

That's a cool age, ahmed                                                                                                     
That's a cool age, 25 

另一个问题: 在

puts "my_name: #{my_name} #{my_name2}"

为什么 #{my_name2} 的值 = 25,而不是 = 艾哈迈德,知道 get_name 方法的最后一行,我返回 name,而不是年龄?

这个问题的简短版本: 请为我跟踪我的代码,告诉我到底发生了什么?

1)get_name方法产生nameadge块。在块内分配了这些变量:name="ahmed", age=25。输出为That's a cool name, ahmed, 25

2)get_name方法将adge成块。在块内分配了这些变量:name=25, adge=nil。(这是一个Proc,而不是lambda,因此它将nil设置为未获得的变量)。输出为That's a cool name, 25,。看到25后的逗号了吗?它实际上也打印nil,但nil.to_s是空字符串。

3) my_name = "艾哈迈德" - 变量被分配

4)由于您的新提示是"输入您的年龄"并且您输入25,因此get_name方法中将其分配给name变量。然后,再次输入 25,该值也会分配给age

5)get_name产生两个值(nameage现在2525)只接受第一个的块。然后get_name生成一个age该块的值。

6)my_name_2=get_name#name=25

你只能使用显式参数形式 (&block) 或yield,但不能两者兼而有之。现在你的&block论点被完全忽略了。

如果使用&block,则可以将yield(替换为block.call(

无论哪种情况,调用堆栈都不是超级复杂。在你调用yield(block.call(的地方,它进入给定的块(你调用puts),然后转到下一行。

另一个需要理解的重要事情是,块不会验证传递给它们的参数数量。有人在StackOverflow评论中给出了一条建议(不知道源链接),我觉得记住它很有帮助。块的行为类似于 proc——它们不验证参数的数量,你可以记住这一点,因为单词是相似的。方法的行为类似于 lamdas——它们确实验证了参数的数量。

因此,当您连续两次调用yield时,这是使用不同的参数多次调用同一块。当您使用不同的do部分调用函数两次时,您将提供两个不同的块

最新更新