Ruby简单程序跟踪(收益 - 方法)

时间:2018-04-07 19:00:21

标签: ruby-on-rails ruby methods yield tracing

这是我根据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-第一次产量"产量名称,年龄"发送回第一个get_name块的名称和年龄,通过| name,age |在块中收到,然后他们都显示在

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

这个

That's a cool name, ahmed, 25 

3-第二次产量"产量年龄"发送回第一个get_name块的年龄只有这个时间,它通过| name,age |在块中收到,这次我们发回块只有一个参数,而block有两个参数,这次是名字块上的参数接收来自" yield name"的年龄参数,而块上的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,而不是= ahmed,知道get_name方法的最后一行,我返回名字,而不是年龄?

本问题的简短版本:  请为我追踪我的代码,告诉我究竟发生了什么?

2 个答案:

答案 0 :(得分:0)

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)由于您的新提示是“输入您的年龄”而您输入的是25,因此会在name方法中将其分配给get_name变量。然后,再次输入25,该值也会分配给age

5)get_name会产生两个值(nameage,现在2525)只占第一个的块。然后get_name会为该块产生一个值age

6)my_name_2=get_name#name=25

答案 1 :(得分:0)

您只能使用显式参数表单(&block)或yield,但不能同时使用两者。现在你的&block参数完全被忽略了。

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

在任何一种情况下,调用堆栈都不是非常复杂。在您调用yield(block.call(时,它会进入给定的块(您调用puts),然后转到下一行。

要理解的另一个重要事项是块不会验证传递给它们的参数数量。有人在StackOverflow评论中提出了一条建议(不知道源链接),我发现这些评论有助于记住。块表现得像procs - 它们不验证参数的数量,你可以记住它,因为单词是相似的。方法表现得像lamdas - 它们确实验证了args的数量。

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