OO Perl : Struggling with hash data members in my Class

B

Brett.R.Davis

I am writing my first Perl Class and have hit a brick wall.

What I need to do is have a class method copy a hash into the data
member %MY_HASH.

I have coded a constructor and a method my_hash which is *supposed* to
either:

1. return the HASH reference or
2. write a copy the contents of a hash into the MY_COLORS data member.

Then I wanted a second data member that uppon being written to with a
symbolic name, would use the MY_COLORS hash to provide the numberical
code for that COLOR as shown:

my $composite_colors={'green'=>1, 'blue'=>2, 'red'=>3 };
my $color_set=Chash->new();
$chash->my_colors($composite_colors);
$chash->color_code('blue');
print $chash{'color_code'};

The output should be:

2

However, I am never able to get the object $chash to take in the
$composite_colors reference, and copy it into the data member
MY_COLORS. I get comments like "odd number of elements in anonymous
hash". If I data dump the contents of the data member MY_COLORS it
shows that the $composite_colors hash is being copied in as a key to
the has instead of essentially becoming the MY_COLORS hash.

Any assistance would be greatly appreciated!!!!

Brett


Here is the code.

package Chash;

sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
$self->{MY_COLORS} = {};
$self->{COLOR_CODE} = undef;
bless($self, $class);
return $self;
}

sub my_colors {
my $self = shift;
if (@_) { $self->{MY_COLORS} = $_[0] }
return { $self->{MY_COLORS} };
}


sub color_code {
my $self = shift;
if (@_) {
if (ref $self->{MY_COLORS} eq "HASH") {
$self->{COLOR_CODE} = $self->{MY_COLORS}->{$_[0]};
}
else {
$self->{COLOR_CODE} = shift;
}
}
return $self->{COLOR_CODE};
}
 
B

Brett.R.Davis

Thank you for your response.
I think my simple color abstraction may have confused the issue.
Let me try to rephrase the problem - given a hash :

my %bar = { 'x'=>0xbeef, 'y'=>0xfeed };

and assuming a class Foo with the constructor below,
how do I put %bar into MY_HASH.

And then how do I get the contents of MY_HASH?

I can't seem to get this to work.

=-=-=-=--=-=-=-=-=-=-=-=-=-

Package My::Class::Foo;

use strict;
use warnings;
use Carp;

sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
$self->{MY_HASH} = {};
bless($self, $class);
return $self;
}

=-=-=-=-=-=-=-=--=-==-=-=-=-=-
 
M

Mumia W.

I am writing my first Perl Class and have hit a brick wall.

What I need to do is have a class method copy a hash into the data
member %MY_HASH.

I have coded a constructor and a method my_hash which is *supposed* to
either:

1. return the HASH reference or
2. write a copy the contents of a hash into the MY_COLORS data member.

Then I wanted a second data member that uppon being written to with a
symbolic name, would use the MY_COLORS hash to provide the numberical
code for that COLOR as shown:

my $composite_colors={'green'=>1, 'blue'=>2, 'red'=>3 };
my $color_set=Chash->new();

I got your program to work, but I had to assign $color_set to
$chash before the line below.
$chash->my_colors($composite_colors);
$chash->color_code('blue');
print $chash{'color_code'};

The output should be:

2

However, I am never able to get the object $chash to take in the
$composite_colors reference, and copy it into the data member
MY_COLORS.

The code you posted pretty much should work so long as $chash
is set to something meaningful. You have an annoying warning
that I'll show you how to get rid of.
I get comments like "odd number of elements in anonymous
hash". If I data dump the contents of the data member MY_COLORS it
shows that the $composite_colors hash is being copied in as a key to
the has instead of essentially becoming the MY_COLORS hash.

Any assistance would be greatly appreciated!!!!

Brett


Here is the code.

package Chash;

sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
$self->{MY_COLORS} = {};
$self->{COLOR_CODE} = undef;
bless($self, $class);
return $self;
}

sub my_colors {
my $self = shift;
if (@_) { $self->{MY_COLORS} = $_[0] }
return { $self->{MY_COLORS} };

The line above produces an annoying warning; the line uses
$self->{MY_COLORS}, which contains only *one* value, a scalar
reference to a hash, as the data for an anonymous hash
(denoted by { ... }); hashes with an uneven number of elements
are usually messed up.

I don't know why you're creating an anonymous hash then
returning it; you already have a much better hash to return in
$self->{MY_COLORS}, so why not just return it? Perhaps you
were thinking of the {...} as a block. Anyway, change it:

return $self->{MY_COLORS};

}


sub color_code {
my $self = shift;
if (@_) {
if (ref $self->{MY_COLORS} eq "HASH") {
$self->{COLOR_CODE} = $self->{MY_COLORS}->{$_[0]};
}
else {
$self->{COLOR_CODE} = shift;
}
}
return $self->{COLOR_CODE};
}

A. Sinan Unur showed you how to use some perl modules to do
this differently, and I think I'll do that too:

package My::Chash2;
use Class::Struct;
struct 'My::Chash2' => [ my_colors => '%' ];

sub color_code {
my $self = shift;
$self->my_colors(shift());
}

package main;

my $composite_colors={'green'=>1, 'blue'=>2, 'red'=>3 };
my $chash = My::Chash2->new();
$chash->my_colors($composite_colors);
print $chash->color_code('blue'), "\n";



__HTH__

:)
 
M

Mumia W.

Thank you for your response.
I think my simple color abstraction may have confused the issue.
Let me try to rephrase the problem - given a hash :

my %bar = { 'x'=>0xbeef, 'y'=>0xfeed };

You have problems with Perl syntax. Curly braces are used to
create blocks and anonymous hashes. Use parenthesis to create
arrays and non-anonymous hashes, e.g.

my %bar = ( 'x'=>0xbeef, 'y'=>0xfeed );

and assuming a class Foo with the constructor below,
how do I put %bar into MY_HASH.

And then how do I get the contents of MY_HASH?

I can't seem to get this to work.

=-=-=-=--=-=-=-=-=-=-=-=-=-

Package My::Class::Foo;

use strict;
use warnings;
use Carp;

sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
$self->{MY_HASH} = {};
%{$self->{MY_HASH}} = @_ if (@_);
bless($self, $class);
return $self;
}

=-=-=-=-=-=-=-=--=-==-=-=-=-=-

package main;

my $chash = My::Class::Foo->new(%bar)

However, I wouldn't bother writing a new() function for
something this simple, because it's so much easier to cheat:

use Class::Struct;
struct My::Class::Foo => [ my_colors => '%' ];

my %bar = ( 'x'=>0xbeef, 'y'=>0xfeed );
my $chash = My::Class::Foo->new( my_colors => \%bar);

=-=-=-=-=-=-=-=--=-==-=-=-=-=-
UNTESTED CODE
 
B

Brett.R.Davis

You said that you were able to get my original code to work.

Can you tell me specifically what it was - or was it the items you
specified in the message?

The class I presented was just for academic reasons. The actual class
I need to implement will be quite a bit more complicated.

Does the struct class you showed me allow for member functions?

Thanks
I am writing my first Perl Class and have hit a brick wall.

What I need to do is have a class method copy a hash into the data
member %MY_HASH.

I have coded a constructor and a method my_hash which is *supposed* to
either:

1. return the HASH reference or
2. write a copy the contents of a hash into the MY_COLORS data member.

Then I wanted a second data member that uppon being written to with a
symbolic name, would use the MY_COLORS hash to provide the numberical
code for that COLOR as shown:

my $composite_colors={'green'=>1, 'blue'=>2, 'red'=>3 };
my $color_set=Chash->new();

I got your program to work, but I had to assign $color_set to
$chash before the line below.
$chash->my_colors($composite_colors);
$chash->color_code('blue');
print $chash{'color_code'};

The output should be:

2

However, I am never able to get the object $chash to take in the
$composite_colors reference, and copy it into the data member
MY_COLORS.

The code you posted pretty much should work so long as $chash
is set to something meaningful. You have an annoying warning
that I'll show you how to get rid of.
I get comments like "odd number of elements in anonymous
hash". If I data dump the contents of the data member MY_COLORS it
shows that the $composite_colors hash is being copied in as a key to
the has instead of essentially becoming the MY_COLORS hash.

Any assistance would be greatly appreciated!!!!

Brett


Here is the code.

package Chash;

sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
$self->{MY_COLORS} = {};
$self->{COLOR_CODE} = undef;
bless($self, $class);
return $self;
}

sub my_colors {
my $self = shift;
if (@_) { $self->{MY_COLORS} = $_[0] }
return { $self->{MY_COLORS} };

The line above produces an annoying warning; the line uses
$self->{MY_COLORS}, which contains only *one* value, a scalar
reference to a hash, as the data for an anonymous hash
(denoted by { ... }); hashes with an uneven number of elements
are usually messed up.

I don't know why you're creating an anonymous hash then
returning it; you already have a much better hash to return in
$self->{MY_COLORS}, so why not just return it? Perhaps you
were thinking of the {...} as a block. Anyway, change it:

return $self->{MY_COLORS};

}


sub color_code {
my $self = shift;
if (@_) {
if (ref $self->{MY_COLORS} eq "HASH") {
$self->{COLOR_CODE} = $self->{MY_COLORS}->{$_[0]};
}
else {
$self->{COLOR_CODE} = shift;
}
}
return $self->{COLOR_CODE};
}

A. Sinan Unur showed you how to use some perl modules to do
this differently, and I think I'll do that too:

package My::Chash2;
use Class::Struct;
struct 'My::Chash2' => [ my_colors => '%' ];

sub color_code {
my $self = shift;
$self->my_colors(shift());
}

package main;

my $composite_colors={'green'=>1, 'blue'=>2, 'red'=>3 };
my $chash = My::Chash2->new();
$chash->my_colors($composite_colors);
print $chash->color_code('blue'), "\n";



__HTH__

:)
 
M

Mumia W.

You said that you were able to get my original code to work.

Can you tell me specifically what it was - or was it the items you
specified in the message?
[...]

Don't top post.

Everything was in the message: I assigned $color_set to
$chash, and I made my_colors() return $self->{MY_COLORS}.
 
B

Brett.R.Davis

OK - it worked!

I am a moron, and didn't have "-w" set in the script so I didn't notice
that I had { } around a hash reference like you said in the above post.
I originally had it as an anonymous hash.

By changing the return statement and fixing my hash declaration (used (
) instead of { } ) - it works!

Thank you

Brett
You said that you were able to get my original code to work.

Can you tell me specifically what it was - or was it the items you
specified in the message?
[...]

Don't top post.

Everything was in the message: I assigned $color_set to
$chash, and I made my_colors() return $self->{MY_COLORS}.
 

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,968
Messages
2,570,150
Members
46,697
Latest member
AugustNabo

Latest Threads

Top