perl feature request

D

dt

I find the following useful and would like to see it as a new perl
feature:

I often have to cache a variable based on a complex function. it owuld
be nice if perl had something like this built in. here is an example:

our $html;
if ($html !~ /./)
{
$html = load_as_string($fh, "filename.html");
}


a datatype such as:

cache $html = load_as_string($fh, "filename.html");

would be really cool. basically, if the var is not set, it sets the
var. if it is set, it skips the call.

it would have to still be there if the function is exited and recalled
(same scope as our).
 
U

Uri Guttman

d> I find the following useful and would like to see it as a new perl
d> feature:

d> I often have to cache a variable based on a complex function. it owuld
d> be nice if perl had something like this built in. here is an example:

d> our $html;

that will mean $html is undef. where would another value come from?

d> if ($html !~ /./)

that will generated an undefined warning.

d> {
d> $html = load_as_string($fh, "filename.html");
d> }


huh? what is wrong with just doing this:

$html ||= load_as_string($fh, "filename.html");

and load_as_string is already in File::Slurp as read_file().


d> a datatype such as:

d> cache $html = load_as_string($fh, "filename.html");

d> would be really cool. basically, if the var is not set, it sets the
d> var. if it is set, it skips the call.

but you can't declare and also optionally assign. where would a preset
value come from??

d> it would have to still be there if the function is exited and recalled
d> (same scope as our).

easy. just declare it my in a block that also includes the sub:

use File::Slurp ;

{

my $html ;

sub do_stuff {

$html ||= read_file( $filename ) ;

}

}

so it already is in perl.

and that only fails if the html file is a false value (just '0', or
empty) which is unlikely.

in perl 5.10 you can do //= and test for defined and that solves that
problem.

uri
 
A

anno4000

Uri Guttman said:
d> I find the following useful and would like to see it as a new perl
d> feature:

d> I often have to cache a variable based on a complex function. it owuld
d> be nice if perl had something like this built in. here is an example:

d> our $html;

that will mean $html is undef. where would another value come from?

From anywhere, it's a package variable. Unlike "my", "our" doesn't
reset the value at run time.

I quite agree with the rest of your posting.

Anno
 
U

Uri Guttman

d> I find the following useful and would like to see it as a new perl
d> feature:d> I often have to cache a variable based on a complex function. it owuld
d> be nice if perl had something like this built in. here is an example:
a> From anywhere, it's a package variable. Unlike "my", "our" doesn't
a> reset the value at run time.

of course i know what our is. but his example didn't show any other
assignment to it. he was looking for a static type variable and our was
all he could come up with. even file scoped my would be fine. the real
point was not knowing about ||=.

a> I quite agree with the rest of your posting.

as do i. :)

uri
 
B

Ben Morrow

Quoth Uri Guttman said:
d> a datatype such as:

d> cache $html = load_as_string($fh, "filename.html");

d> would be really cool. basically, if the var is not set, it sets the
d> var. if it is set, it skips the call.

but you can't declare and also optionally assign. where would a preset
value come from??

d> it would have to still be there if the function is exited and recalled
d> (same scope as our).

easy. just declare it my in a block that also includes the sub:

<code snipped>

I was going to say 'in 5.10 this exact feature has been included, as the
new 'state' variables', but perlsub says

| B<Caveat>: the code at the right side of the assignment to a state
| variable will be executed every time; only the assignment is disabled.
| So, avoid code that has side-effects, or that is slow to execute. This
| might be optimized out in a future version of Perl.

Doesn't this make state variables, uh, rather useless? Given that they
are basically exactly equivalent to your example above, so all you save
is one compile-time block? Have I missed something?
and that only fails if the html file is a false value (just '0', or
empty) which is unlikely.

in perl 5.10 you can do //= and test for defined and that solves that
problem.

....well, unless undef is *also* a valid return value :). Also (to the
OP) note that testing for defined is perfectly possible in current
perls, just rather awkward:

{
my $html;

sub foo {
defined $html or $html = load_as_string(...);
}
}

An alternative solution to look into is Memoize. It has a rather
different set of appropriate uses, but if you [one] find yourself
[s himself] creating a whole lot of these loaded-only-once variables it
may be easier just to memoize the loading function.

Ben
 
U

Uri Guttman

BM> <code snipped>

BM> I was going to say 'in 5.10 this exact feature has been included, as the
BM> new 'state' variables', but perlsub says

BM> | B<Caveat>: the code at the right side of the assignment to a state
BM> | variable will be executed every time; only the assignment is disabled.
BM> | So, avoid code that has side-effects, or that is slow to execute. This
BM> | might be optimized out in a future version of Perl.

BM> Doesn't this make state variables, uh, rather useless? Given that they
BM> are basically exactly equivalent to your example above, so all you save
BM> is one compile-time block? Have I missed something?

well, it works fine for expressions with no side effects from what i
understand. so you can initilize it one time and the other times it gets
executed the expression results are tossed away. it would work in the
OP's example but it would cost a full file slurp each time. but if you
did something like state $foo = [ 1, 2, 3 ] then you would have that
only assigned the first time and then the [ 1, 2, 3] would still be
evaluated and then tossed away. yes it is clunky and not optimized. if
you care, then use the my in a private block with the sub and ||=.

uri
 
A

anno4000

Ben Morrow said:
<code snipped>

I was going to say 'in 5.10 this exact feature has been included, as the
new 'state' variables', but perlsub says

| B<Caveat>: the code at the right side of the assignment to a state
| variable will be executed every time; only the assignment is disabled.
| So, avoid code that has side-effects, or that is slow to execute. This
| might be optimized out in a future version of Perl.

Doesn't this make state variables, uh, rather useless? Given that they
are basically exactly equivalent to your example above, so all you save
is one compile-time block? Have I missed something?

No, they're not useless because they keep their value from one call to
another, while still being lexical variables. Currently, we must
declare a lexical variable outside the sub for that purpose.

Anno
 
A

anno4000

Uri Guttman said:
d> I find the following useful and would like to see it as a new perl
d> feature:
d> I often have to cache a variable based on a complex function. it owuld
d> be nice if perl had something like this built in. here is an example:

a> From anywhere, it's a package variable. Unlike "my", "our" doesn't
a> reset the value at run time.

of course i know what our is.

I know you do, but what you said seemed to imply otherwise.

Anno
 
B

Ben Morrow

Quoth (e-mail address removed)-berlin.de:
No, they're not useless because they keep their value from one call to
another, while still being lexical variables. Currently, we must
declare a lexical variable outside the sub for that purpose.

Yes, I realise that. What I was saying is that if

sub foo {
state $foo;
...;
}

is equivalent to

{
my $foo;
sub foo {
...;
}
}

is this really terribly useful? I suppose if you had something like

sub foo {
# lotsa stuff

{
state $foo;
...;
}
}

then you've gained a decrease in scope, but why not just use another
sub? Is there some other use case I'm missing?

Ben
 
A

anno4000

Ben Morrow said:
Quoth (e-mail address removed)-berlin.de:

Yes, I realise that. What I was saying is that if

sub foo {
state $foo;
...;
}

is equivalent to

{
my $foo;
sub foo {
...;
}
}

is this really terribly useful?

That is, of course, a judgement call.

I have never been happy about having to use a bare block, and an extra
level of indentation, just to introduce a state-keeping variable.

Bare blocks containing lexicals and a set of functions to access them
are a useful means for structuring code. If you *have* to use that
technique for a single function and one or a few (state-) variables that
are conceptually part of the sub, that blurs the image and makes the
structure less obvious.
I suppose if you had something like

sub foo {
# lotsa stuff

{
state $foo;
...;
}
}

then you've gained a decrease in scope, but why not just use another
sub? Is there some other use case I'm missing?

I don't know of any though I'm sure people will come up with the
weirdest uses for state variables. It's a small step that gets rid
of a small nuisance in Perl programming.

Compare it to the introduction of the fat comma "=>". All it does is
allow barewords on its left, a ridiculously small difference in the
abstract. Yet it has become very much part of the language.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top