How to explain callbacks in plain English? How are they different from calling one function from another function taking some context from the calling function? How can thei
Often an application needs to execute different functions based upon its context/state. For this, we use a variable where we would store the information about the function to be called. According to its need the application will set this variable with the information about function to be called and will call the function using the same variable.
In javascript, the example is below. Here we use method argument as a variable where we store information about function.
function processArray(arr, callback) {
var resultArr = new Array();
for (var i = arr.length-1; i >= 0; i--)
resultArr[i] = callback(arr[i]);
return resultArr;
}
var arr = [1, 2, 3, 4];
var arrReturned = processArray(arr, function(arg) {return arg * -1;});
// arrReturned would be [-1, -2, -3, -4]
I am going to try to keep this dead simple. A "callback" is any function that is called by another function which takes the first function as a parameter. A lot of the time, a "callback" is a function that is called when something happens. That something can be called an "event" in programmer-speak.
Imagine this scenario: you are expecting a package in a couple of days. The package is a gift for your neighbor. Therefore, once you get the package, you want it brought over to the neighbors. You are out of town, and so you leave instructions for your spouse.
You could tell them to get the package and bring it to the neighbors. If your spouse was as stupid as a computer, they would sit at the door and wait for the package until it came (NOT DOING ANYTHING ELSE) and then once it came they would bring it over to the neighbors. But there's a better way. Tell your spouse that ONCE they receive the package, they should bring it over the neighbors. Then, they can go about life normally UNTIL they receive the package.
In our example, the receiving of the package is the "event" and the bringing it to the neighbors is the "callback". Your spouse "runs" your instructions to bring the package over only when the package arrives. Much better!
This kind of thinking is obvious in daily life, but computers don't have the same kind of common sense. Consider how programmers normally write to a file:
fileObject = open(file)
# now that we have WAITED for the file to open, we can write to it
fileObject.write("We are writing to the file.")
# now we can continue doing the other, totally unrelated things our program does
Here, we WAIT for the file to open, before we write to it. This "blocks" the flow of execution, and our program cannot do any of the other things it might need to do! What if we could do this instead:
# we pass writeToFile (A CALLBACK FUNCTION!) to the open function
fileObject = open(file, writeToFile)
# execution continues flowing -- we don't wait for the file to be opened
# ONCE the file is opened we write to it, but while we wait WE CAN DO OTHER THINGS!
It turns out we do this with some languages and frameworks. It's pretty cool! Check out Node.js to get some real practice with this kind of thinking.
Imagine you need a function that returns 10 squared so you write a function:
function tenSquared() {return 10*10;}
Later you need 9 squared so you write another function:
function nineSquared() {return 9*9;}
Eventually you will replace all of these with a generic function:
function square(x) {return x*x;}
The exact same thinking applies for callbacks. You have a function that does something and when done calls doA:
function computeA(){
...
doA(result);
}
Later you want the exact same function to call doB instead you could duplicate the whole function:
function computeB(){
...
doB(result);
}
Or you could pass a callback function as a variable and only have to have the function once:
function compute(callback){
...
callback(result);
}
Then you just have to call compute(doA) and compute(doB).
Beyond simplifying code, it lets asynchronous code let you know it has completed by calling your arbitrary function on completion, similar to when you call someone on the phone and leave a callback number.
A metaphorical explanation:
I have a parcel I want delivered to a friend, and I also want to know when my friend receives it.
So I take the parcel to the post office and ask them to deliver it. If I want to know when my friend receives the parcel, I have two options:
(a) I can wait at the post office until it is delivered.
(b) I will get an email when it is delivered.
Option (b) is analogous to a callback.
I think it's an rather easy task to explain.
At first callback are just ordinary functions.
And the further is, that we call this function (let's call it A) from inside another function (let's call it B).
The magic about this is that I decide, which function should be called by the function from outside B.
At the time I write the function B I don't know which callback function should be called. At the time I call function B I also tell this function to call function A. That is all.
What Is a Callback Function?
The simple answer to this first question is that a callback function is a function that is called through a function pointer. If you pass the pointer (address) of a function as an argument to another, when that pointer is used to call the function it points to it is said that a call back is made.
Callback function is hard to trace, but sometimes it is very useful. Especially when you are designing libraries. Callback function is like asking your user to gives you a function name, and you will call that function under certain condition.
For example, you write a callback timer. It allows you to specified the duration and what function to call, and the function will be callback accordingly. “Run myfunction() every 10 seconds for 5 times”
Or you can create a function directory, passing a list of function name and ask the library to callback accordingly. “Callback success() if success, callback fail() if failed.”
Lets look at a simple function pointer example
void cbfunc()
{
printf("called");
}
int main ()
{
/* function pointer */
void (*callback)(void);
/* point to your callback function */
callback=(void *)cbfunc;
/* perform callback */
callback();
return 0;
}
How to pass argument to callback function?
Observered that function pointer to implement callback takes in void *, which indicates that it can takes in any type of variable including structure. Therefore you can pass in multiple arguments by structure.
typedef struct myst
{
int a;
char b[10];
}myst;
void cbfunc(myst *mt)
{
fprintf(stdout,"called %d %s.",mt->a,mt->b);
}
int main()
{
/* func pointer */
void (*callback)(void *); //param
myst m;
m.a=10;
strcpy(m.b,"123");
callback = (void*)cbfunc; /* point to callback function */
callback(&m); /* perform callback and pass in the param */
return 0;
}