Skip to content

Instantly share code, notes, and snippets.

@mikebannister
Created August 30, 2011 13:42
Show Gist options
  • Save mikebannister/1180910 to your computer and use it in GitHub Desktop.
Save mikebannister/1180910 to your computer and use it in GitHub Desktop.
In a lot of languages callbacks are really common. You might call a function
with another function as an argument and at some point
in the body of the called function the callback function gets called. You said
this is done with pointers in C... not sure how
common this is there so bear with me.
# This is (psuedo-code) based on javascript where callbacks are really common
because it's asynchronous (i.e. you often need a callback to be notified when
the function you've called is complete). First two function definitions:
function a_function_that_takes_a_function_as_an_argument(a_regular_argument, a_function_argument) {
print "We're inside a_function_that_takes_a_function_as_an_argument"
print 'A regular argument: ' + a_regular_argument;
print 'OK, all done, calling back to caller'
a_function_argument(a_regular_argument);
}
function another_function(a_regular_argument) {
print 'OK, the other function is finally done! (We're inside another_function)'
print 'The other function gave us back this argument: ' + a_regular_argument
}
# Now we call the first function with the second one as an argument
a_function_that_takes_a_function_as_an_argument('a string', another_function);
# The output should look like
We're inside a_function_that_takes_a_function_as_an_argument
A regular argument: a string
OK, all done, calling back to caller
OK, the other function is finally done! (We're inside another_function)
The other function gave us back this argument: a string
So! In Ruby you can't pass functions around in the same way but instead we have
blocks which can do 'all that and more'. Notice, you call 'yield' to execute
the block. Notice also that you don't have to do anything special in Ruby to
declare that your function takes a block, it's built-in.
One function:
def a_function_that_accepts_a_code_block(a_regular_argument)
print "We're inside a_function_that_takes_a_code_block"
print 'A regular argument: ' + a_regular_argument;
print 'OK, all done, calling back to caller'
yield a_regular_argument
end
Call it with a block:
a_function_that_takes_a_code_block do |a_regular_argument|
print "OK, the other function is finally done! (We're inside another_function)"
print 'The other function gave us back this argument: ' + a_regular_argument
end
This is really powerful and is used all over the Ruby language and Ruby On Rails.
A very common pattern that the author of functions in ruby uses is 1) the function
does 'some stuff' 2) the function calls the block (with yield) one or many times
and 3) the function does some more stuff (like cleanup). A great example of this
is ruby's built in function for reading and writing files:
File.open('/path/to/file/somewhere, 'w') do |the_file|
the_file.write('some text')
end
So you can imagine the definition for this function 1) opens the file, 2) calls yield
so the caller do whatever it wants with the open file and 3) flushes the output and
closes the file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment