![]() |
|
Your skill will accomplish what the force of many cannot |
|
PerlMonks |
Re: Ways to implement a closureby tmoertel (Chaplain) |
on Oct 15, 2004 at 21:07 UTC ( #399664=note: print w/replies, xml ) | Need Help?? |
(Updated 20041017: Added final, put-it-all-togther example.)
While closures are almost always created via anonymous subroutines (a la sub { ... }) at the lowest level, the real fun only comes about when you delegate this chore to some kind helper function that builds anonymous subroutines for you. Thus, in heavily functional code, you usually don't use sub { } yourself but instead rely upon a library of helpers to do the grunt work for you. For example, here's a function that builds functions to append a given suffix to strings: It takes a given suffix, remembers it, and returns a new function that will apply the remembered suffix to any string we give it: We can have even more fun if we create higher-order functions that remember other functions in their closures. Here's a pair of functions that can be used to apply other functions to a list of arguments as a whole or to each argument, one at a time: We might use them like so: We can also capture regex values in closures to good effect: Now we can use the helper function to build "regex matchers": Why would we want to make all these little functions? Because we can glue them together to make complicated things happen. One of the most fundamental kinds of glue is composition, which turns individual functions into function pipelines: Now let's glue some of our earlier functions together to make some simple pipelines: Also, note that we don't need to store our pipelines in a variable before we use them. We can call them on the fly: Note that when building pipelines using compose, the input data flows through the functions right-to-left (following mathematical convention). Watch what happens if we parenify first and then match for words: As a final example, let's build 27 different pipeline combinations from our earlier collection of functions and see what each pipeline does when applied to a reference string. To help us out, let's first build id – the identity function – which simply returns its input as its output. We'll use it to pass data through stages of our pipeline unchanged. And now, our pipeline playground: Here's the output: I hope this gives you some idea of how you can create and benefit from closures without directly having to create anonymous subroutines. Just create helper functions to do the work for you. Cheers, P.S. For a more practical fun-with-closures example, see Re: Redirecting STDOUT from internal function with 5.6.1 restrictions, which shows how to capture output from a filehandle (such as STDOUT or STDERR) temporarily. Tom Moertel : Blog / Talks / CPAN / LectroTest / PXSL / Coffee / Movie Rating Decoder
In Section
Seekers of Perl Wisdom
|
|