puts "\nWays of creating a basic block:"

def pass_me_a_block_please
yield
end

pass_me_a_block_please {
puts "* Put it in brackets."
}

pass_me_a_block_please { puts "* In curly brackets, all on one line!" }

pass_me_a_block_please do
puts "* Ooh. You're using 'do' to create a block."
end

puts "\nWhat happens if you don't pass a block?"

begin
pass_me_a_block_please
rescue LocalJumpError
puts "* Oops! Calling yield without passing a block raises a LocalJumpError"
end

puts "\nYou can use block_given? to test if a block has been passed."

def pass_me_a_block_if_you_want_to
if block_given?
puts "* If you can read this, you DID pass a block, and it's about to be evaluated:"
yield
else
puts "* If you can read this, you didn't pass in a block."
end
end

puts "About to not pass a block!"
pass_me_a_block_if_you_want_to # This is okay

puts "About to pass a block!"
pass_me_a_block_if_you_want_to { # So is this!
puts "* If you can read this, the block you just passed has been evaluated!"
}

puts "\nYou can also just rescue the error if you don't pass in a block:"

def pass_me_a_block_if_you_want_to
begin
yield
rescue LocalJumpError
puts "* You didn't pass a block, but at least you rescued the error."
end
end

pass_me_a_block_if_you_want_to

puts "\nLet's write a method with arguments AND a block!"

def pass_me_some_args(arg1, arg2)
puts arg1
puts arg2
yield
end

pass_me_some_args("one", "two") {
puts "three"
}

puts "\nAn ampersand before the last method argument means it's a block."

def pass_me_some_args_with_named_block_arg(arg1, arg2, &arg3)
puts "\npass_me_some_args_with_named_block_arg"
puts arg1
puts arg2
if arg3 # You can also test for a block like this if you have named it.
puts "You passed a block named arg3 which is about to be evaluated:"
yield
else
puts "No block passed."
end
end

pass_me_some_args_with_named_block_arg("one", "two")

pass_me_some_args_with_named_block_arg("one", "two") {
puts "three"
}

puts "\nWhat about variable scope?"

i_am_a_variable_already_defined = "defined_before_the_block_is_called"
pass_me_a_block_please {
i_am_a_variable_already_defined = "i_can_be_changed_within_a_block"
}

puts "i_am_a_variable_already_defined: #{i_am_a_variable_already_defined}"

pass_me_a_block_please {
i_am_just_a_local_variable = "the_answer_to_life_the_universe_and_everything"
}

begin
puts "i_am_just_a_local_variable: #{i_am_just_a_local_variable}"
rescue NameError
puts "we'll never know what was in i_am_just_a_local_variable"
end

def change_variable_in_the_method
i_am_a_variable_local_to_this_method = "you_cant_change_me_in_the_block_about_to_be_called"
yield
puts "i_am_a_variable_local_to_this_method: #{i_am_a_variable_local_to_this_method}"
end

change_variable_in_the_method {
i_am_a_variable_local_to_this_method = "this won't change anything!!"
}

begin
puts "i_am_a_variable_local_to_this_method: #{i_am_a_variable_local_to_this_method}"
rescue NameError
puts "I told you it was just local to that method!"
end