Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re: Trying to Understand Callback(s)

by GrandFather (Saint)
on Nov 23, 2017 at 23:22 UTC ( [id://1204176] : note . print w/replies, xml ) Need Help??


in reply to Trying to Understand Callback(s)

Callbacks are a way of getting some user supplied code run in a provider context. The "user" is your code. The "provider" is some fancy pants module or sub written by someone else (or by you being clever). I'm sure you are happy to pass parameters into a sub so the sub can do some work with them. Well, a callback is just some code (a reference to a sub) that you pass as a parameter so the called sub can do some work with it.

Why would you want to do that? In the example you give (I'm guessing) you are providing a sub that will get called to handle web page that has been fetched. In other cases you might provide a callback to do some math on data points as part of an algorithm that searches for patterns in a data set. The search algorithm remains the same for different match conditions - you are passing in the bit that is tuned for a specific type of match.

So the parameter you are passing is just a reference to a sub (that's the \& bit). That can be provided in a bunch of different ways and may often use closures to pass some of your calling context into the callback - that is deep magic indeed! Let's take a look:

use strict; use warnings; my $helloWorld = sub{return "Hello world 1"}; process($helloWorld); process(sub{return "Hello world 2"}); process(\&helloWorld); process(sub{return $_}) for 1 .. 5; process(sub{mul10($_)}) for 1 .. 5; sub helloWorld { return "Hello World 3"; } sub mul10 { my ($x) = @_; return $x * 10; } sub process { my ($callback) = @_; print $callback->(), "\n"; }

Prints:

Hello world 1 Hello world 2 Hello World 3 1 2 3 4 5 10 20 30 40 50

The process calls with (sub...) are all creating a sub on the fly. sub returns a reference to the subroutine. You can see that with $helloWorld. The \& variant calls a sub defined somewhere else. The last two with the for loop modifiers use closures to pass the default variable into the called subroutine. Closures are subtle and can do astounding things - in fact quite often what they do is astounding in a disconcerting way!

As a matter of course I use a line of the form my ($p1, $p2, $p3, ...) = @_; to provide local variables containing the values of passed in parameters. @_ is the list of aliases to the parameters passed to the sub.  my (...) declares a list of variables that get assigned values from the @_ parameter list. You can use undef as a place holder for a parameter that you aren't interested in - i.e.: to ignore the parameter.

Premature optimization is the root of all job security