这是我根据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方法的最后一行,我返回名字,而不是年龄?
本问题的简短版本: 请为我追踪我的代码,告诉我究竟发生了什么?
答案 0 :(得分:0)
1)get_name
方法将name
和adge
生成块。在块中,这些变量被分配: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
会产生两个值(name
和age
,现在25
和25
)只占第一个的块。然后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
部分调用该函数两次时,您提供两个不同的块。