ruby code get blocked on
yes it's mostly about blocks
def try_a_new_hobby(hobby = "literally anything")
puts "I will surely pick up #{hobby} this time"
sleep
yield(hobby)
end
try_a_new_hobby("sewing") { |hobby| puts "I learned to #{hobby}!" }Did you know the sleep method waits forever if you don't give it a number?I meant to write my first post here about how I think using blocks in ruby is fun but then I got distracted thinking about how I get distracted.
I forget when I need the & when using a block and when I don't, so I'm going to learn right now and post it here so I have a reference I can bookmark.
Here are some methods to try out:
def takes_a_block(&block)
puts "block taken"
yield
puts "gives block back"
endthe basic - calling the block with a block runs the code given where yield is
# remember do/end is the same as `takes_a_block { puts "I'm from the block" }`
takes_a_block do
puts "I've been yielded"
end
#=> block taken
#=> I've been yielded
#=> gives block back Do you need to have the &block parameter when defining the method?
def takes_a_block
puts "block taken"
yield
puts "gives block back"
endRunning this with a block like before returns the same result, but reduces readability, especially if the method you are looking at is longer than 3 lines.
What happens when you don't pass in a block?
takes_a_block
#=> 'Object#takes_a_block': no block given (yield) (LocalJumpError)yield will throw an error if you don't give it a block
UNLESS you only let the method yield when a block is given:
def takes_a_block
puts "block taken"
yield if block_given?
puts "gives block back"
endsee:
takes_a_block
#=> block taken
#=> gives block backnow back to why I'm writing this post, the &
for this to matter we can't pass the block as do/end or {}
we'll save our block as a proc
my_block = proc { puts "i'm in the block" }then see what happens if you call our method with and without the &
takes_a_block(&myblock) # with &
#=> block taken
#=> i'm in the block
#=> gives block backtakes_a_block(myblock) # no &
#=> 'takes_a_block': wrong number of arguments (given 1, expected 0) (ArgumentError)Oops, All Errors
What it comes down to is that the & tells ruby to try and call a variable like a proc. So without the ampersand here, the `takes_a_block` method is upset because we gave it a parameter it didn't want.
bonus - update?
rewriting the method to have a &block parameter doesn't change the error message!
def takes_a_block(&my_block)will still return wrong number of arguments (given 1, expected 0) (ArgumentError)
This is because, (I have only talked to friends about this, I'll actually dive into the ruby source code eventually, but I do have, like, a real job to be doing) when you define a method with a &block parameter, you enable yourself to reference that parameter within the method as block.