Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > access anonymous variable

Reply
Thread Tools

access anonymous variable

 
 
George Mpouras
Guest
Posts: n/a
 
      02-01-2011
At the following example I want to alter the value of $counter variable ,
but without using the the $iter code reference.
I 've tried many tricks using __ANON__ but without luck . Can you help ?


my $iter = Create_counter( 37);

for (1..3)
{
print "$_) ". $iter->() ."\n"
}

sub Create_counter
{
my $counter = $_[0];

return sub
{
$counter++
}
}



 
Reply With Quote
 
 
 
 
Ted Zlatanov
Guest
Posts: n/a
 
      02-01-2011
On Tue, 1 Feb 2011 14:20:58 +0200 "George Mpouras" <(E-Mail Removed)> wrote:

GM> At the following example I want to alter the value of $counter variable ,
GM> but without using the the $iter code reference.
GM> I 've tried many tricks using __ANON__ but without luck . Can you help ?

GM> my $iter = Create_counter( 37);

GM> for (1..3)
GM> {
GM> print "$_) ". $iter->() ."\n"
GM> }

GM> sub Create_counter
GM> {
GM> my $counter = $_[0];

GM> return sub
GM> {
GM> $counter++
GM> }
GM> }

Here's one way:

#!/usr/bin/perl

use warnings;
use strict;
use Modern:erl;

{
my $counter = 0;

sub get_counter
{
$counter = shift @_ if scalar @_;
return \$counter;
}
}

${get_counter(37)}++; # increments the hidden $counter, starting at 37
say ${get_counter()};
${get_counter()}++; # increments the hidden $counter
say ${get_counter()};

This passes around a reference to a scoped variable; there's no other
way to access $counter outside its scope and the value of $counter will
persist between get_counter() calls.

I'll warn you that this is probably the wrong way to go unless you
really need this and know why. Can you explain your requirements a
little bit?

Ted
 
Reply With Quote
 
 
 
 
Peter Makholm
Guest
Posts: n/a
 
      02-01-2011
"George Mpouras" <(E-Mail Removed)> writes:

> At the following example I want to alter the value of $counter variable ,
> but without using the the $iter code reference.


If you really need this, it can be done with the PadWalker module. But
I would recommend against it unless you know what you are doing and
are sure that you need to do it.

//Makholm
 
Reply With Quote
 
George Mpouras
Guest
Posts: n/a
 
      02-01-2011
Στις 1/2/2011 5:25 μμ, ο/η Ted Zlatanov *γραψε:
> On Tue, 1 Feb 2011 14:20:58 +0200 "George Mpouras"<(E-Mail Removed)> wrote:
>
> GM> At the following example I want to alter the value of $counter variable ,
> GM> but without using the the $iter code reference.
> GM> I 've tried many tricks using __ANON__ but without luck . Can you help ?
>
> GM> my $iter = Create_counter( 37);
>
> GM> for (1..3)
> GM> {
> GM> print "$_) ". $iter->() ."\n"
> GM> }
>
> GM> sub Create_counter
> GM> {
> GM> my $counter = $_[0];
>
> GM> return sub
> GM> {
> GM> $counter++
> GM> }
> GM> }
>
> Here's one way:
>
> #!/usr/bin/perl
>
> use warnings;
> use strict;
> use Modern:erl;
>
> {
> my $counter = 0;
>
> sub get_counter
> {
> $counter = shift @_ if scalar @_;
> return \$counter;
> }
> }
>
> ${get_counter(37)}++; # increments the hidden $counter, starting at 37
> say ${get_counter()};
> ${get_counter()}++; # increments the hidden $counter
> say ${get_counter()};
>
> This passes around a reference to a scoped variable; there's no other
> way to access $counter outside its scope and the value of $counter will
> persist between get_counter() calls.
>
> I'll warn you that this is probably the wrong way to go unless you
> really need this and know why. Can you explain your requirements a
> little bit?
>
> Ted



I was doing some experiments after a discussion with my colleague about
iterators and how they can protect their variables. I thought I could
find a way for direct access private variable of an anonymous subroutine
but maybe it is impossible after all. They are completely invisible.

use Data:umper;
$Data:umper:eparse=1;
print STDOUT Data:umper:umper(\%{__PACKAGE__.'::'});




 
Reply With Quote
 
Ted Zlatanov
Guest
Posts: n/a
 
      02-03-2011
On Tue, 01 Feb 2011 22:35:55 +0200 George Mpouras <(E-Mail Removed)> wrote:

GM> I was doing some experiments after a discussion with my colleague
GM> about iterators and how they can protect their variables. I thought I
GM> could find a way for direct access private variable of an anonymous
GM> subroutine but maybe it is impossible after all. They are completely
GM> invisible.

GM> use Data:umper;
GM> $Data:umper:eparse=1;
GM> print STDOUT Data:umper:umper(\%{__PACKAGE__.'::'});

The example I gave shows how to have a scope that keeps a private
variable whose value is preserved between subroutine calls, which is
usually what an iterator needs. If you explain your actual need, it
would help us answer your question better.

Ted
 
Reply With Quote
 
jl_post@hotmail.com
Guest
Posts: n/a
 
      02-04-2011




On Feb 1, 5:20*am, "George Mpouras"
<(E-Mail Removed)> wrote:
> At the following example I want to alter the value of $counter variable ,
> but without using the the $iter code reference.
> I 've tried many tricks using __ANON__ but without luck . Can you help ?
>
> my $iter = Create_counter( *37);
>
> for (1..3)
> {
> print "$_) ". $iter->() ."\n"
> }
>
> sub Create_counter
> {
> my $counter = $_[0];
>
> return sub
> * {
> * $counter++
> * }
> }



Dear George,

The problem with trying to alter the $counter variable is that it
is a variable that only gets modified inside the Create_counter()
subroutine and the function it returns.

Basically, you're using a closure. Read up on "perldoc -q closure"
for a better idea of what a closure is.

When you assign the subroutine reference to $iter with the line:

my $iter = Create_counter(37);

you're giving $iter the only power to modify the $counter variable
that was created in the call to Create_counter() . From here on, the
only way to modify that specific instance of $counter is to call $iter-
>() .


You can change all that if you modify the code, however. If you
change the Create_counter() subroutine to look like:

sub Create_counter
{
my $counter = $_[0];

return \$counter, sub { $counter++ }
}

then you can call it like this:

my ($counterRef, $iter) = Create_counter(37);

and you can see and modify the value of the $counter by printing or
assigning to $$counterRef (note the double '$' -- that's not a typo).
What's more is that you can still call Create_counter() the old way,
like this:

my $iter = Create_counter(37);

which will just discard the $counterRef part (due to assigning to a
scalar). However, if you do this, then you lose the ability to
observe and modify the $counter instance that $iter->() uses (other
than just calling $iter->(), of course).

If you prefer to avoid references, you can write Create_counter()
this way:

sub Create_counter
{
my $counter = $_[0];

return sub { $counter }, # getter
sub { $counter = $_[0] }, # setter
sub { $counter++ } # iterator
}

This will allow you to write code like this:

my ($getter, $setter, $iter) = Create_counter(37);

print $iter->(); # prints 37 and sets $counter to 38
print $getter->(); # prints out $counter, which is 38
$setter->(5); # sets $counter to 5
print $iter->(); # prints 5 and sets $counter to 6

So if you want to be able to read/modify the $counter variable that
$iter->() uses (without using $iter), you have to somehow return
access to it, by either returning a reference to it, or by returning
another sub { } that can read/modify it.

I hope this helps, George.

Have a great day!

-- Jean-Luc
 
Reply With Quote
 
sln@netherlands.com
Guest
Posts: n/a
 
      02-04-2011
On Fri, 4 Feb 2011 11:04:01 -0800 (PST), "(E-Mail Removed)" <(E-Mail Removed)> wrote:

>
>
>
>
>On Feb 1, 5:20*am, "George Mpouras"
><(E-Mail Removed)> wrote:
>> At the following example I want to alter the value of $counter variable ,
>> but without using the the $iter code reference.
>> I 've tried many tricks using __ANON__ but without luck . Can you help ?
>>
>> my $iter = Create_counter( *37);
>>
>> for (1..3)
>> {
>> print "$_) ". $iter->() ."\n"
>> }
>>
>> sub Create_counter
>> {
>> my $counter = $_[0];
>>
>> return sub
>> * {
>> * $counter++
>> * }
>> }

>
>
>Dear George,
>
> The problem with trying to alter the $counter variable is that it
>is a variable that only gets modified inside the Create_counter()
>subroutine and the function it returns.
>
> Basically, you're using a closure. Read up on "perldoc -q closure"
>for a better idea of what a closure is.
>
> When you assign the subroutine reference to $iter with the line:
>
> my $iter = Create_counter(37);
>
>you're giving $iter the only power to modify the $counter variable
>that was created in the call to Create_counter() . From here on, the
>only way to modify that specific instance of $counter is to call $iter-
>>() .


What about:

return sub {
if ($_[0]) {
$counter = $_[0];
} else {
* $counter++
}

then $iter->(0) and $iter->(),
or is that too much out of range of the intended use of an itterator?

-sln
 
Reply With Quote
 
jl_post@hotmail.com
Guest
Posts: n/a
 
      02-05-2011
On Feb 4, 4:17*pm, (E-Mail Removed) wrote:
>
> What about:
>
> *return sub {
> * * * * * if ($_[0]) {
> * * * * * * *$counter = $_[0];
> * * * * * } else {
> * * * * * * *$counter++
> * * * *}
>
> then $iter->(0) and *$iter->(),
> or is that too much out of range of the intended use of an itterator?



That would work for setting $counter -- but only to a non-zero
value. (The way it is now, $iter->(0) will increment $counter.)

As for peeking at the value of $counter (that is, reading it
without modifying it), you might have to do this:

print $iter->( $iter->() );

but that might still increment the $counter, depending on when exactly
the '++' operator decides to fire off. (I'm not sure if that's well
defined in this case or not.)

Cheers,

-- Jean-Luc
 
Reply With Quote
 
sln@netherlands.com
Guest
Posts: n/a
 
      02-05-2011
On Fri, 4 Feb 2011 16:17:15 -0800 (PST), "(E-Mail Removed)" <(E-Mail Removed)> wrote:

>On Feb 4, 4:17*pm, (E-Mail Removed) wrote:
>>
>> What about:
>>
>> *return sub {
>> * * * * * if ($_[0]) {
>> * * * * * * *$counter = $_[0];
>> * * * * * } else {
>> * * * * * * *$counter++
>> * * * *}
>>
>> then $iter->(0) and *$iter->(),
>> or is that too much out of range of the intended use of an itterator?

>
>
> That would work for setting $counter -- but only to a non-zero
>value. (The way it is now, $iter->(0) will increment $counter.)
>
> As for peeking at the value of $counter (that is, reading it
>without modifying it), you might have to do this:
>
> print $iter->( $iter->() );
>
>but that might still increment the $counter, depending on when exactly
>the '++' operator decides to fire off. (I'm not sure if that's well
>defined in this case or not.)
>


'if ($_[0])' I didn't see that foible.

I guess poke and peak could be done
*return sub {
* * * * * if (defined $_[0]) {
* * * * * * *$counter = $_[0];
* * * * * } else {
* * * * * * *$counter++
* * * *}
print $iter->( $iter->() - 1 ); # but this isin't understandable

or ---
*return sub {
* * * * * if (defined $_[0]) {
* * * * * * *$counter = ($_[0] =~ /[a-zA-Z]/) ? $counter : $_[0];
* * * * * } else {
* * * * * * *$counter++
* * * *}
print $iter->( 'getval' );
print $iter->(0);

As long as the itterator does its main function correctly,
anything could be done in the sub, right?

-sln
 
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
Is this a local anonymous class or a member anonymous class Reporter Java 3 05-12-2007 05:23 AM
variable interpolation of refs to anonymous subroutines cartercc@gmail.com Perl Misc 29 05-19-2006 05:32 PM
"anonymous" variable in Perl? Ronald Fischer Perl Misc 10 08-09-2005 08:15 PM
help with an anonymous array of anonymous hashes noeldamonmiller@gmail.com Perl Misc 1 02-10-2005 01:08 AM
Network File access using anonymous access Tim Menninger ASP .Net Security 2 07-22-2004 03:37 PM



Advertisments