this is a code I created based on a video course about Ruby blocks on the ruby tracks on TeamTreeHouse, here are the code and it's outputs..
My code:
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}"
My Output:
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
the problem with that code is that when tracing it, I find the output irrelevant, here's what I think must be happened:
1- the first get_name block sent a prompt with question "enter your name", and then the method get_name first print the phrase "enter your name" which comes as parameter called prompt, then the method takes the name as input and takes the age as input
2- the first yield "yield name,age" send back to the first get_name block the name and age, which got received in the block through |name, age| , then they both got displayed in
puts "That's a cool name, #{name}, #{age}"
as this
That's a cool name, ahmed, 25
3- the second yield "yield age" send back to the first get_name block the age only this time, which got received in the block through |name, age|, this time since we sent back to the block only one argument, while the block has two parameters, this time the name parameter on the block received the age argument coming from "yield name", while the age parameter on the block received nothing, so in the block, the #{name} only displays value while the #{age} displays nothing
puts "That's a cool name, #{name}, #{age}"
as this
That's a cool name, 25,
is my tracing true ? because if it's true why in the second get_name block, which is
my_name2 = get_name("enter your age") do |age|
puts "That's a cool age, #{age}"
end
the output was:
That's a cool age, 25
That's a cool age, 25
instead of:
That's a cool age, ahmed
That's a cool age, 25
another question: in
puts "my_name: #{my_name} #{my_name2}"
why the value of #{my_name2} = 25, not = ahmed, knowing that the last line in the get_name method, I returns name, not age ?
SHORT VERSION OF THIS QUESTION: please trace my code for me, tell me what exactly's happening ?
1) get_name
method yields name
and adge
into block. Inside a block these variables are assigned: name="ahmed", age=25
. The output is That's a cool name, ahmed, 25
2) get_name
method yields adge
into block. Inside a block these variables are assigned: name=25, adge=nil
. (that is a Proc, not lambda, hence it sets nil
to variables which were not gotten). The output is That's a cool name, 25,
. See the comma after 25
? It actually prints nil
too, but nil.to_s
is empty string.
3) my_name = "ahmed" - variable is assigned
4) Since your new prompt is "enter your age" and you are entering 25, It is assigned to name
variable in get_name
method. Then, you enter 25 again and that value becomes assigned to age
as well.
5) get_name
yields two values (name
and age
which are now 25
and 25
) the block which takes only the first one. Then get_name
yields one value age
to that block.
6) my_name_2=get_name#name=25