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

Ruby Simple Program Tracing (Yield - Method)

这是我根据有关 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 块发送一个带有问题 "enter your name" 的提示,然后方法 get_name 首先打印短语 "enter your name" 作为参数调用提示, 然后该方法将名称作为输入并将年龄作为输入

2- 第一个 yield "yield name,age" 将名字和年龄发送回第一个 get_name 区块,通过 |name, age| 在区块中收到。 , 然后它们都显示在

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

这样

That's a cool name, ahmed, 25 

3- 第二个 yield "yield age" 这次只发送回第一个 get_name 区块年龄,它是通过 |name, age| 在区块中接收到的,这次我们发送了回到 block 只有一个参数,而 block 有两个参数,这次 block 上的 name 参数收到了来自 "yield name" 的 age 参数,而 block 上的 age 参数什么也没收到,所以在 block 中, #{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,不是=ahmed,知道get_name方法的最后一行,我returns名字,不是年龄?

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

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 = "ahmed" - 变量被赋值

4) 由于您的新提示是 "enter your age" 而您输入的是 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 的位置),然后转到下一行。

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

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