CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
closure - set hash key value

 



waltz
Novice

May 19, 2011, 12:28 AM

Post #1 of 13 (2725 views)
closure - set hash key value Can't Post

Hello,

what i doing wrong ? ..i want set hash key value with function.

Code


Code
sub o { 
my $h = {};

return sub {
if ($#_ > -1){
$h->{name} = shift;
}

return { # hash
"name" => $h->{name},
"set" => sub { $h->{name} = shift; }
}
}
}

my $x = o->("namea");

print "1 " . $x->{name} . "\n";
$x->{set}->("nameA");
print "2 " . $x->{name};


# output

1 namea
2 namea

Thank for your help


miller
User

May 19, 2011, 1:35 AM

Post #2 of 13 (2723 views)
Re: [waltz] closure - set hash key value [In reply to] Can't Post

You're returning a new anonymous hash instead of the one that you defined $h. The following is a simplified version of what you really want:


Code
use strict; 
use warnings;

sub o {
my %h;

if (@_){
$h{name} = shift;
}

$h{set} = sub { $h{name} = shift; };

return \%h;
}


my $x = o("namea");

print "1 " . $x->{name} . "\n";

$x->{set}("nameA");

print "2 " . $x->{name};


- Miller


waltz
Novice

May 19, 2011, 1:50 AM

Post #3 of 13 (2721 views)
Re: [miller] closure - set hash key value [In reply to] Can't Post

Sorry, i was not more precisely.

Im trying set $h anonymous hash as private variable.

Your example not solve what i want...


waltz
Novice

May 20, 2011, 12:22 AM

Post #4 of 13 (2689 views)
Re: [waltz] closure - set hash key value [In reply to] Can't Post

Hello,

this is my modest solution (i know, blessing is better..but i dont know, how i can use / create geters and seters with blessing - presently :o )

->


Code
#!/usr/bin/perl -w 
package Myclass;

use strict;

sub new { # constructor
my $this = {};

return sub {
if ($#_ > -1) {
$this->{name} = shift;

return sub {
# private seters
if ((caller() eq __PACKAGE__)) {
if ($_[0] eq "set") {
return sub { $this->{name} = shift; }
}
}

# public geters
if ($_[0] eq "get") {
return $this->{name};
}
}
}
}
}

sub test {
my $o = Myclass::new->("a");
my $o2 = Myclass::new->("b");

print "o\t" . $o->("get") . "\n";
print "o2\t" . $o2->("get") . "\n";

$o->("set")->("a2"); # ok, if called ftom this module
$o2->("set")->("b2"); # ok, if called ftom this module

print "o\t" . $o->("get") . "\n";
print "o2\t" . $o2->("get") . "\n";
}

return 1;



miller
User

May 20, 2011, 11:08 AM

Post #5 of 13 (2652 views)
Re: [waltz] closure - set hash key value [In reply to] Can't Post

If you don't know how to do OOP, just say so mate. This hacking of closures is not what you want to do.


Code
#!/usr/bin/perl -w  
package Myclass;

use strict;

sub new { # constructor
my $pkg = shift;
my $self = bless {}, $pkg;
$self->set(@_) if @_;
return $self;
}

sub set {
my $self = shift;
$self->{name} = shift;
}

sub get {
my $self = shift;
return $self->{name};
}

package main;

my $o = Myclass->new("a");
my $o2 = Myclass->new("b");

print "o\t" . $o->get() . "\n";
print "o2\t" . $o2->get() . "\n";

$o->set("a2"); # ok, if called ftom this module
$o2->set("b2"); # ok, if called ftom this module

print "o\t" . $o->get() . "\n";
print "o2\t" . $o2->get() . "\n";


Look at the following resource for a list of tutorials on object oriented programming in perl:

http://perldoc.perl.org/index-tutorials.html

- Miller


waltz
Novice

May 23, 2011, 4:15 AM

Post #6 of 13 (2547 views)
Re: [waltz] closure - set hash key value [In reply to] Can't Post

..or other solution - we can define local function in package:

my $private_method = sub {
...
}


FishMonger
Veteran / Moderator

May 23, 2011, 8:04 AM

Post #7 of 13 (2527 views)
Re: [waltz] closure - set hash key value [In reply to] Can't Post

An OO module is not required when writing closures. A quick google search will give you many examples/tutorials.

Here's one taken from: http://www.perl.com/pub/2002/05/29/closure.html


Code
    sub make_counter { 
my $start = shift;
return sub { $start++ }
}

my $from_ten = make_counter(10);
my $from_three = make_counter(3);

print $from_ten->(); # 10
print $from_ten->(); # 11
print $from_three->(); # 3
print $from_ten->(); # 12
print $from_three->(); # 4



waltz
Novice

Jun 14, 2011, 3:58 AM

Post #8 of 13 (2329 views)
Re: [waltz] closure - set hash key value [In reply to] Can't Post

Hello,

see code bellow:


Code
package Test; 

sub new {
my $this = {};
my $pkg = shift;

# constructor
%{$this} = @_ if (scalar(@_) > 0);

bless sub {
if (scalar(@_) > 1) { # setters..
$this->{$_[0]} = $_[1];
}
else { # getters..
return $this->{$_[0]};
}
}, $pkg;
}

sub get {
my $this = shift;

return &{$this}($_[0]);
}

sub set {
my $this = shift;

return &{$this}($_[0], $_[1]);
}

1;

package Main;

my $a = Test->new('a', 'a set', 'aa', 'aa set');
my $b = Test->new('b', 'b set', 'bb', 'bb set');

print "res a\t" . $a->get('a') . "\n";
print "res b\t" . $b->get('b') . "\n";

$a->set('a', 'a2 test');
$b->set('b', 'b2 test');

# after..
print "res a\t" . $a->get('a') . "\n";
print "res b\t" . $b->get('b');


..and look on this page:

http://www.perlmonks.org/?node_id=8251

R.


miller
User

Jun 14, 2011, 9:42 AM

Post #9 of 13 (2317 views)
Re: [waltz] closure - set hash key value [In reply to] Can't Post

You're getting absolutely no value from implementing things in this way, and are in fact just making things harder to maintain.

What is your goal? Are you simply trying to make it so that the state variables of each object are hidden?

If that's the case, then just use one of the many methods that are much more modern than a post from the year 2000. At the very least, you should pick up O'Reilly's Perl Best Practices, which details a way to create 'inside-out objects' like done in Class::Std.

Either way, you're suffering from an X-Y problem here. You're focussed on accomplishing Y, because you thought it was the best way to do X. But instead, you should just list problem X to us, as I guarantee that someone will have a better solution than the one that you're attempting.

- Miller


waltz
Novice

Jun 15, 2011, 4:28 AM

Post #10 of 13 (2311 views)
Re: [miller] closure - set hash key value [In reply to] Can't Post

Hi,

i like playing (learning) with Perl, im a beginner..anyway you're right that trying obsolete OOP technics its not good.

Now i looking at module Class-InsideOut-1.10 ..i hope its a good way :)

Thank for alignment

R.


waltz
Novice

Jun 17, 2011, 1:04 AM

Post #11 of 13 (2283 views)
Re: [waltz] closure - set hash key value [In reply to] Can't Post

Hi,

i thinking about this inside-out contruction:


Code
 
package Class;
use Scalar::Util qw/refaddr/;

{
my %a;
my %b;

sub new {
my $scalar;
my $pkg = shift;

$a{ refaddr \$scalar } = shift;
$b{ refaddr \$scalar } = shift;

bless \$scalar, $pkg;
}

sub getA { my $self = shift; return $a{ refaddr $self }; }
sub getB { my $self = shift; return $b{ refaddr $self }; }
}


..question is, can i use code bellow ? its clean ? ..one hash using anonymous hash with key attributes..


Code
package Class; 
use Scalar::Util qw/refaddr/;

{
my %h;

sub new {
my $scalar;
my $pkg = shift;

$h{ refaddr \$scalar } = {
'a' => shift,
'b' => shift
};

bless \$scalar, $pkg;
}

sub getA { my $self = shift; return $h{ refaddr $self }->{a}; }
sub getB { my $self = shift; return $h{ refaddr $self }->{b}; }
}


..and final question: why it is necessary use address key in hashes ?? ..

Thank

R.


waltz
Novice

Jun 17, 2011, 2:41 AM

Post #12 of 13 (2281 views)
Re: [waltz] closure - set hash key value [In reply to] Can't Post

sorry, i forgot:

..blessed scalar address ensure that hash attribute will not rewrite..(from other object instances)

R.


miller
User

Jun 17, 2011, 10:39 AM

Post #13 of 13 (2264 views)
Re: [waltz] closure - set hash key value [In reply to] Can't Post


In Reply To
..question is, can i use code bellow ? its clean ? ..one hash using anonymous hash with key attributes..

...

..and final question: why it is necessary use address key in hashes ?? ..


Having a separate hash for every attribute has two benefits.

1) It documents your code. It is very easy for someone else, or even yourself to look at your code and immediately know what the attributes are for a particular class. Ideally you'd also give them meaningful names, something other than 'a' and 'b'.

2) It provides syntax checking. Mistyping the key name in a hash of hash will not provide any type of error message. However, if you mistype the name of the hash, perl will report the error when use strict is on (as it always should be).

As for the second question, you already answered it. Yes, using the reference address makes each object unique.

- Miller

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives