Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Using closures with "use strict"

Reply
Thread Tools

Using closures with "use strict"

 
 
Ben Morrow
Guest
Posts: n/a
 
      06-23-2004

Quoth ddtl <this.is@invalid>:
>
> If I define a "use strict" and want to create a closure,
> how can I refer to the anonymous functions defined in that
> closure? Consider the following example:
>
> -------------------------------------------
> use strict;
>
> {
> our $f = sub {print "Hi\n";};
> }
>
> &$f;
> -------------------------------------------
>
> Here compiler complains, and reports an error:
>
> "Variable "$f" is not imported at ~/test line 7."


The variable declared by 'our' is a lexically-scoped alias to the
package global, so you need to put it in the same place as you would put
an equivalent 'my' variable. What you want is

use strict;

our $f;
{
# presumably there is more code here?

$f = sub {...};
}

# I prefer this style of indirect function call, as it matches the other
# deref ops and doesn't lead to potential confusion about calling named
# subs with &.

$f->();

or perhaps

our $f = do {
...
sub {...};
};

Ben

--
All persons, living or dead, are entirely coincidental.
http://www.velocityreviews.com/forums/(E-Mail Removed) Kurt Vonnegut
 
Reply With Quote
 
 
 
 
David K. Wall
Guest
Posts: n/a
 
      06-23-2004
ddtl <this.is@invalid> wrote in message
<news:(E-Mail Removed) >:

> If I define a "use strict" and want to create a closure,
> how can I refer to the anonymous functions defined in that
> closure? Consider the following example:
>
> -------------------------------------------
> use strict;
>
> {
> our $f = sub {print "Hi\n";};
>}
>
> &$f;
> -------------------------------------------


That doesn't fit my idea of a closure. It's just a code reference.
As you noted, the code above is broken because variables declared
with our() are lexically scoped.

A closure (as I understand it) is a subroutine that keeps track of
lexical variables that are within scope when that subroutine is
defined, so that later it can still access those variables even
though they're out of the present scope.

For example:

use strict;

my $f;
{
my $string = 'test';
sub set_string { $string = $_[0] }
sub get_string { $string }
$f = \&get_string;
}

print get_string(), "\n";
set_string('something else');
print get_string(), "\n";

# call get_string() using a code reference
print $f->(), "\n";

# this statement will generate an error, because $string is
# now out of scope
print "\$string = $string\n";


set_string() and get_string() are closures. $f is just a code
reference to what happens to be a closure.

 
Reply With Quote
 
 
 
 
ddtl
Guest
Posts: n/a
 
      06-23-2004

Hello,

If I define a "use strict" and want to create a closure,
how can I refer to the anonymous functions defined in that
closure? Consider the following example:

-------------------------------------------
use strict;

{
our $f = sub {print "Hi\n";};
}

&$f;
-------------------------------------------

Here compiler complains, and reports an error:

"Variable "$f" is not imported at ~/test line 7."

Obviously, though 'f' is declared using 'our' modifier, as there
is no such a global variable called 'f', using 'our $f;' creates
some kind of restricted global variable (don't know even how to
call it - that variable works like a global one, but it's "globalness"
is restricted to the enclosing block).

In order to rectify it (and still have the benefits of "use strict",
there are two possibilities that I can see:

1) Enclose closure and every call to anonymous function defined in
the closure in "no strict":

------------------------------------
use strict;

{
no strict;
$f = sub {print "Hi\n";};
use strict;

}

#...
#...

no strict;
&$f;
use strict;
#...
#...
------------------------------------

2) Define all the references to anonymous functions in closure as
"our $REF_NAME" somewhere outside the block:


------------------------------------
use strict;

{
our $f = sub {print "Hi\n";};
}
our $f;

&$f;
------------------------------------


Another solution can maybe involve some tricks with package declarations,
but I am only in the "Chapter 8" of "Programming Perl", so I can't
be sure.


The problem is, that all those solutions are looking very contrived
and ugly.

Is there is a better way to do that?


ddtl.


 
Reply With Quote
 
Malcolm Dew-Jones
Guest
Posts: n/a
 
      06-23-2004
ddtl (this.is@invalid) wrote:

: Hello,

: If I define a "use strict" and want to create a closure,
: how can I refer to the anonymous functions defined in that
: closure? Consider the following example:

: -------------------------------------------
: use strict;

: {
: our $f = sub {print "Hi\n";};
: }

: &$f;
: -------------------------------------------

: Here compiler complains, and reports an error:

: "Variable "$f" is not imported at ~/test line 7."

: Obviously, though 'f' is declared using 'our' modifier, as there
: is no such a global variable called 'f', using 'our $f;' creates
: some kind of restricted global variable (don't know even how to
: call it - that variable works like a global one, but it's "globalness"
: is restricted to the enclosing block).
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Yes (sort of), that's what "our" does. It tells the compiler you intend
to access the global variable $f, but only within the current scope.

If you intend to access the same global variable within a different scope
then it must also be defined within that different scope as well.

There are various things you could do. (most examples untested)

#1
use strict;
my $f;
{
$f = sub {print "Hi\n";};
}
&$f;

#2
use strict;
our $f;
{
$f = sub {print "Hi\n";};
}
&$f;

#3
use strict;
{
our $f = sub {print "Hi\n";};
}
our $f;
&$f;
#4
use strict;
{
our $f = sub {print "Hi\n";};
}
{
our $f;
&$f;
}

#5
use strict;
yse vars '$f';
{
$f = sub {print "Hi\n";};
}
&$f;

and possibly others. Unless $f must be accessed by routines in different
files then the #1 (my $f) is probably best. However, "our" does have the
advantage that you can declare it within smaller blocks as needed (#4),
which makes it available to less than the entire file (unlike my, where
everything after the declaration must see the variable if any of the code
is to see it).
 
Reply With Quote
 
Tad McClellan
Guest
Posts: n/a
 
      06-24-2004
ddtl <this.is@invalid> wrote:

> If I define a "use strict" and want to create a closure,


> -------------------------------------------
> use strict;
>
> {
> our $f = sub {print "Hi\n";};
> }
>
> &$f;
> -------------------------------------------



There is no closure there you know.

Maybe your question is how to make a closure or what constitutes
a "closure"?


> Obviously, though 'f' is declared using 'our' modifier, as there
> is no such a global variable called 'f', using 'our $f;' creates
> some kind of restricted global variable (don't know even how to
> call it - that variable works like a global one, but it's "globalness"
> is restricted to the enclosing block).



I think you are confusing the scope of the _name_ of the variable
with being able to access the value of the variable.

You can always access package variables (so they are "global").

All our() does for you is give you temporary ('til end of block)
permission to use short names instead of fully qualified names.

with our($x):

print $x;


without our($x):

print $main:;

or

print $Cool:ackage:;


You can access the value at any place in the code, its value is global.

You can access the value by the "short name" only in the our()'s scope.


> Is there is a better way to do that?



I think the other followups have already done that part.


--
Tad McClellan SGML consulting
(E-Mail Removed) Perl programming
Fort Worth, Texas
 
Reply With Quote
 
ddtl
Guest
Posts: n/a
 
      06-24-2004

>> -------------------------------------------
>> use strict;
>>
>> {
>> our $f = sub {print "Hi\n";};
>>}
>>
>> &$f;
>> -------------------------------------------

>
>That doesn't fit my idea of a closure. It's just a code reference.
>As you noted, the code above is broken because variables declared
>with our() are lexically scoped.
>
>A closure (as I understand it) is a subroutine that keeps track of
>lexical variables that are within scope when that subroutine is
>defined, so that later it can still access those variables even
>though they're out of the present scope.


You are right of course - this is not actually a closure, but was just too
lazy to type the whole ~10 more characters to provide anonymous sub
with it's "personal" scoped variables . Anyway, the question was clearly
understood by everybody, despite of my lazyness.

ddtl.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Using closures and partial functions to eliminate redundant code Matthew Wilson Python 6 09-27-2007 09:14 AM
using closures as a replacement for "class", @, and @@ Eric Mahurin Ruby 0 06-25-2007 04:35 PM
using javascript closures to create singletons to ensure the survival of a reference to an HTML block Jake Barnes Javascript 2 02-12-2006 02:09 PM



Advertisments