Callback
A callback is a function which is passed as an argument to another function.
The most direct application of a callback is when a particular function is applied to a collection of values.
Some languages support a block syntax for some iterative operations (like Ruby's Array#each
), whereas other languages support functions as first-class citizens, meaning that functions act like other values and can thus be passed as arguments explicitly.
(in Ruby)
numbers = [10, 20, 30, 40]
# Some callbacks can be written as unnamed blocks
numbers.each do |number|
puts number * 2
end
# Other callbacks may be assigned to a variable before use
capitalize_word = lambda { |word| word.capitalize }
"every word should be capitalized".split(" ").map(&capitalize_word)
(in JavaScript)
var numbers = [10, 20, 30, 40];
// Some callbacks can be written as anonymous functions
numbers.forEach(function(number) {
console.log(number * 2);
});
// Other callbacks may be assigned to a variable before use
var capitalizeWord = function(word) {
return word.charAt(0).toUpperCase() + word.substring(1);
};
"every word should be capitalized".split(" ").map(capitalizeWord);
An additional feature of callbacks is that they do not necessarily have to be executed immediately. They can be kept for future use, which makes them a very flexible tool.
The following example shows one way in which you could use callbacks to model an emergency dispatch system, providing pre-defined actions (i.e. callbacks) to be executed when an emergency happens.
(in Ruby)
class EmergencyDispatch
def initialize
# Store responses to emergencies in a hash
@responses = {}
end
# Register a particular response with a type of emergency
def register(emergency_type, response)
@responses[emergency_type] = response
end
# When the emergency occurs, execute the response function
def notify(emergency_type)
callback = @responses[emergency_type]
raise "Don't know how to respond to #{emergency_type}, sorry" unless callback
callback.call
end
end
dispatcher = EmergencyDispatch.new
# Our dispatcher will be able to respond to crimes and fires
dispatcher.register("crime", -> { puts "Send the police!" })
dispatcher.register("fire", -> { puts "Send the firefighters!" })
# When a new emergency occurs, we notify the dispatcher
dispatcher.notify("fire")
dispatcher.notify("crime")
# What happens when an unexpected event occurs?
dispatcher.notify("Godzilla")
(in JavaScript)
var EmergencyDispatch = function() {
// Store responses to emergencies in an object
this.emergencies = {};
}
// Register a particular response with a type of emergency
EmergencyDispatch.prototype.register = function(emergencyType, response) {
this.emergencies[emergencyType] = response;
};
// When the emergency occurs, execute the response function
EmergencyDispatch.prototype.notify = function(emergencyType) {
var response = this.emergencies[emergencyType];
if (!response) {
throw "Don't know how to respond to " + emergencyType + ", sorry";
}
response();
};
var dispatcher = new EmergencyDispatch();
// Our dispatcher will be able to respond to crimes and fires
dispatcher.register("crime", function() { console.log("Send the police!"); });
dispatcher.register("fire", function() { console.log("Send the firefighters!"); });
// When a new emergency occurs, we notify the dispatcher
dispatcher.notify("crime");
dispatcher.notify("fire");
// What happens when an unexpected event occurs?
dispatcher.notify("Godzilla");