Search code examples
ruby-on-railsrubymethodsyieldtrace

Ruby Simple Program Tracing (Yield - Method)


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 ?


Solution

  • 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