Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Re^3: closures: anonymous subs vs function templates?

by Athanasius (Archbishop)
on Dec 21, 2014 at 16:45 UTC ( [id://1110967]=note: print w/replies, xml ) Need Help??


in reply to Re^2: closures: anonymous subs vs function templates?
in thread closures: anonymous subs vs function templates?

Hello Laurent_R,

I think you are correct: your example code does seem to fulfil the requirements for a closure according to the Wikipedia article Closure_(computer_programming). And at the start of the tutorial Closure on Closures, broquaint takes a similar view:

However, I believe this isn't entirely accurate as a closure in perl can be any subroutine referring to lexical variables in the surrounding lexical scopes.

But, as you point out, this type of closure isn’t very useful, since there is no way to change the value of $add from outside the block. And if we try to return a reference to a named function from within another function, it doesn’t work as required:

#! perl use strict; use warnings; use v5.14; sub make_add { my $addpiece = shift; sub add { my $c = shift; return ($c + $addpiece); } return \&add; } my $f1 = make_add(20); my $f2 = make_add(35); say $f1->(10); say $f2->(10);

Output:

2:40 >perl 1102_SoPW.pl Variable "$addpiece" will not stay shared at 1102_SoPW.pl line 9. 30 30 2:40 >

Hope that helps,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^4: closures: anonymous subs vs function templates?
by Laurent_R (Canon) on Dec 21, 2014 at 17:51 UTC
    Well, there are cases where you can actually do something useful with named closures. Consider this example, a very simplified version of part of a module I wrote at work a few years ago. I wanted the module to "remember" about error buffer pointer, connection id and transaction id returned by a database application, without the user of the module having to worry about these internals. I used something like this to build two closures acting as a mutator and an accessor:
    { my ($error_buff_p, $connection_id, $transaction_id); my $init_done = 0; sub get_val {return ($error_buff_p, $connection_id, $transaction_id +, $init_done);}; sub set_val { ($error_buff_p, $connection_id, $transaction_id, $ini +t_done) = @_;}; }
    Now, somewhere else in the same module, I had an init_connection function, which called the application API to open the connection to the database and to get these identifiers. That init_connection sub called the set_val function, passing it the parameters. Once this is done, the parameters are stored within the two closures. And other subs in my module could call the get_val sub to obtain the stored parameters when needed. This enabled me to make those pieces of data persistent and relatively strongly encapsulated within the module.

    It could be made in many other ways (anonymous closures, objects, even lexical variables global to the module, etc.), and I would probably do it differently today (probably with anonymous subs), but I found this to be a quite lightweight solution to my needs at the time.

    Having said that, I think that we both agree the anonymous closures are most of the time more useful and more practical. Especially when you want your function to return a code_ref to the caller, as your example shows.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1110967]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (7)
As of 2024-04-19 07:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found