Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Using lock_keys with strict and bless

Reply
Thread Tools

Using lock_keys with strict and bless

 
 
lroland@gmail.com
Guest
Posts: n/a
 
      08-08-2005
Hi

I am trying to use "lock_keys" to create a unmodifiable perl module -
my code is inspired by this article
http://perltraining.com.au/tips/2005-01-31.html - I figured that if I
do the following in my constructor then it works:

----------------
my %i = ( name => undef );
bless \%i, 'Misc';
lock_keys(%i);
----------------

unfortunately this is not very handy in a perl module rather than using
a explicit hash I would like to use a reference in the style of:

----------------
package Misc::Misc;

use diagnostics;
use warnings;
use strict;

use Hash::Util qw(lock_keys);
use Data:umper;

sub new
{
my ($this) = @_;
bless {
name => undef,
info => {
age => undef
}
}, $this;
lock_keys(%$this); # this does not work
}

sub print
{
my ($this) = @_;
my $content = Dumper($this);
print "Hash content is:\n $content";
}

1;
----------------

This does however not work, when trying to use the module:

----------------
#!/usr/bin/perl
use strict;
use Misc::Misc;

my $test = Misc::Misc->new();
$test->{name} = "foobar";
$test->{info}->{age} = "42";
$test->print();
----------------

perl complaints about wrong usage of strict refs - so does anyone know
if lock_keys somehow can be used in a perl module such as the one
created above ?


--
Lars Roland

 
Reply With Quote
 
 
 
 
Paul Lalli
Guest
Posts: n/a
 
      08-08-2005
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> ----------------
> package Misc::Misc;
>
> use diagnostics;
> use warnings;
> use strict;
>
> use Hash::Util qw(lock_keys);
> use Data:umper;
>
> sub new
> {
> my ($this) = @_;
> bless {
> name => undef,
> info => {
> age => undef
> }
> }, $this;
> lock_keys(%$this); # this does not work
> }


You seem to be confused about how Perl modules work. In your code,
$this is the class of which new() is a member. You cannot dereference
$this as a hash, because it isn't a hash reference - or any reference
for that matter. Your bless() statement blesses an anonymous hash into
the class $class. Unfortunately, you did not provide any method by
which to store this hash reference.

Furthermore, you also apparently haven't read the documentation for the
function your using.
http://search.cpan.org/~nwclark/perl...tricted_hashes
tells us: "Note: the current implementation prevents the hash from
being bless()ed while it is in a locked state. Any attempt to do so
will raise an exception. Of course you can still bless() the hash
before you call lock_keys() so this shouldn't be a problem."


> This does however not work, when trying to use the module:
>
> ----------------
> #!/usr/bin/perl
> use strict;
> use Misc::Misc;
>
> my $test = Misc::Misc->new();
> $test->{name} = "foobar";
> $test->{info}->{age} = "42";
> $test->print();
> ----------------
>
> perl complaints about wrong usage of strict refs


Please read the positing guidelines for this group. Specifically, do
not give us the general theme of the error message - copy and paste the
*exact* error message. Had you taken the time to look at what that
error message actually told you: "Can't use string ("Misc::Misc") as a
HASH ref while "strict refs" in use at Misc.pm line 19 (#1)", you might
have been able to figure out that this error message had nothing to do
with the lock_keys method.

> - so does anyone know
> if lock_keys somehow can be used in a perl module such as the one
> created above ?


Not the way you created it above, no. Again, read the documentation
for the function you created, and then apply it to the standard way a
constructor is written.
Step 1: get the class name
Step 2: create the hash reference
Step 3: bless the hash reference into the class
Step 4: lock the keys of the hash the reference references
Step 5: return the blessed reference

checkout
perldoc perlmod
perldoc perlobj
perldoc perloot

for more information on creating classes.

Hope this helps,
Paul Lalli

 
Reply With Quote
 
 
 
 
lroland@gmail.com
Guest
Posts: n/a
 
      08-08-2005
Paul Lalli wrote:
> You seem to be confused about how Perl modules work. In your code,
> $this is the class of which new() is a member. You cannot dereference
> $this as a hash, because it isn't a hash reference - or any reference
> for that matter. Your bless() statement blesses an anonymous hash into
> the class $class. Unfortunately, you did not provide any method by
> which to store this hash reference.


Thanks for the reply - if I however change the code to

-----------
package Misc::Misc;
use strict;
use Data:umper;
use Hash::Util qw(lock_keys);

sub new
{
my ($this) = @_;
my $struct = {
name => undef,
info => {
age => undef
}
};
bless $struct, $this;
lock_keys(%$struct);
}
sub print
{
my ($this) = @_;
my $content = Dumper($this);
print "Hash content is:\n $content";
}
1;
-----------

When I try to execute the following code:

-----------
use Misc::Misc;
my $test = Misc::Misc->new();
$test->{name} = "foobar";
$test->{info}->{age} = "42";
$test->print();
-----------

then I get the following error: "can't call method "print" on unblessed
reference at misc.pl" - I realize that I have misunderstood something
important here, but I have googled around, read the man pages and none
of them seams to deal with locking the content of a hash used
internally in a module (although some of them mention it is possible).

> Furthermore, you also apparently haven't read the documentation for the
> function your using.
> http://search.cpan.org/~nwclark/perl...tricted_hashes
> tells us: "Note: the current implementation prevents the hash from
> being bless()ed while it is in a locked state. Any attempt to do so
> will raise an exception. Of course you can still bless() the hash
> before you call lock_keys() so this shouldn't be a problem."
>


Well I may be off (still new to OO perl) but the docs says "Of course
you can still bless() the hash before you call lock_keys()" - when I
do:

-----------
bless $struct, $this;
lock_keys(%$struct);
-----------

is that not the same as a bless before locking ?.


--
Lars Roland

 
Reply With Quote
 
Paul Lalli
Guest
Posts: n/a
 
      08-08-2005
(E-Mail Removed) wrote:
> -----------
> package Misc::Misc;
> use strict;
> use Data:umper;
> use Hash::Util qw(lock_keys);
>
> sub new
> {
> my ($this) = @_;
> my $struct = {
> name => undef,
> info => {
> age => undef
> }
> };
> bless $struct, $this;
> lock_keys(%$struct);
> }


I'm going to paste back in my "five steps" that you snipped:
> > Step 1: get the class name
> > Step 2: create the hash reference
> > Step 3: bless the hash reference into the class
> > Step 4: lock the keys of the hash the reference references
> > Step 5: return the blessed reference


You have skipped step 5.

> When I try to execute the following code:
>
> -----------
> use Misc::Misc;
> my $test = Misc::Misc->new();
> $test->{name} = "foobar";
> $test->{info}->{age} = "42";
> $test->print();
> -----------
>
> then I get the following error: "can't call method "print" on unblessed
> reference at misc.pl" - I realize that I have misunderstood something
> important here, but I have googled around, read the man pages and none
> of them seams to deal with locking the content of a hash used
> internally in a module (although some of them mention it is possible).


That's because this has nothing to do with locking. You're assigning
$test to be the return value of the call to new(). Perl subroutines
return the last statement evaluated. In this case, that's the
lock_keys() call. lock_keys() does not return your blessed reference.
So $test does not contain your blessed reference. Add this line to the
end of your constructor:

return $struct;

> Well I may be off (still new to OO perl) but the docs says "Of course
> you can still bless() the hash before you call lock_keys()" - when I
> do:
>
> -----------
> bless $struct, $this;
> lock_keys(%$struct);
> -----------
>
> is that not the same as a bless before locking ?.


That section of the code is 100% fine. Nothing wrong there.

Paul Lalli

 
Reply With Quote
 
lroland@gmail.com
Guest
Posts: n/a
 
      08-08-2005
Paul Lalli wrote:
> I'm going to paste back in my "five steps" that you snipped:
> > > Step 1: get the class name
> > > Step 2: create the hash reference
> > > Step 3: bless the hash reference into the class
> > > Step 4: lock the keys of the hash the reference references
> > > Step 5: return the blessed reference

>
> That's because this has nothing to do with locking. You're assigning
> $test to be the return value of the call to new(). Perl subroutines
> return the last statement evaluated. In this case, that's the
> lock_keys() call. lock_keys() does not return your blessed reference.
> So $test does not contain your blessed reference. Add this line to the
> end of your constructor:
>
> return $struct;


Thanks a lot for your help - I think I get your point - I seam to fail
seeing the relationship between the internal struct and the
encapsulation performed by bless - this is somewhat different to what I
am used to in C++. I will try to get my hands on the OO perl book by
Damian Conway so I can get this right.

changing the module to:

------------
package Misc::Misc;
use strict;
use Data:umper;
use Hash::Util qw(lock_keys);

sub new
{
my ($this) = @_;
my $struct = {
name => undef,
info => {
age => undef
}
};
bless $struct, $this;
lock_keys(%$struct);
return $struct;
}
sub print
{
my ($this) = @_;
my $content = Dumper($this);
print "Hash content is:\n $content";
}
1;
------------

does indeed make the code work but it does not ensure that the entire
data structure is locked - if I execute the following code:

------------
#/usr/bin/perl
use Strict;
use Misc::Misc;
my $test = Misc::Misc->new();
# change values is ok
$test->{name} = "foobar";
$test->{info}->{age} = "42";
# this should not could happen
$test->{info}->{fail} = "12";
#print object
$test->print();
------------

then the resulting structure contains a key which was not created in in
the constructor (i.e. {info}->{fail} )- Without having researched this
further I am guessing that I it is because I am using a hash of hashes
and lock_keys properly only function on the outer hash not the inner
one.

--
Lars Roland

 
Reply With Quote
 
Paul Lalli
Guest
Posts: n/a
 
      08-08-2005
(E-Mail Removed) wrote:
> Thanks a lot for your help - I think I get your point - I seam to fail
> seeing the relationship between the internal struct and the
> encapsulation performed by bless - this is somewhat different to what I
> am used to in C++. I will try to get my hands on the OO perl book by
> Damian Conway so I can get this right.


My appreciation for Mr. Conway's work notwithstanding, I would still
recommend reading the free documentation that comes with Perl before
spending money on a book. See if you can understand how to make your
code work by reading the various references and tutorials.

perldoc perlref - Reference about references
perldoc perllol - Building "lists of lists"
perldoc perldsc - Data Structures Cookbook
perldoc perlobj - Perl objects
perldoc perltoot - Object Oriented Tutorial
perldoc perlmod - Modules and Namespaces
perldoc perlnewmod - Writing your own new module


> sub new
> {
> my ($this) = @_;
> my $struct = {
> name => undef,
> info => {
> age => undef
> }
> };
> bless $struct, $this;
> lock_keys(%$struct);
> return $struct;
> }


> does not ensure that the entire data structure is locked - if I
> execute the following code:
>
> ------------
> #/usr/bin/perl
> use Strict;
> use Misc::Misc;
> my $test = Misc::Misc->new();
> # change values is ok
> $test->{name} = "foobar";
> $test->{info}->{age} = "42";
> # this should not could happen
> $test->{info}->{fail} = "12";
> #print object
> $test->print();
> ------------
>
> then the resulting structure contains a key which was not created in in
> the constructor (i.e. {info}->{fail} )- Without having researched this
> further I am guessing that I it is because I am using a hash of hashes
> and lock_keys properly only function on the outer hash not the inner
> one.


Mostly Correct. The hash that you locked contains exactly 2 keys -
'name' and 'info'. The *value* of the hash at the key 'info' is a
reference to another hash. That hash is not locked. You could, of
course, lock it:
lock_keys(%{$struct->{info}});

Paul Lalli

 
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
Bless Matz and his teammates in Japan Joey Zhou Ruby 7 03-14-2011 04:27 AM
YAML and Bless to dump subset of object fails for me Rud1ger Sch1erz Perl Misc 1 11-16-2007 07:51 PM
God Bless The Alabama Crimson Tide Ctrl¤/Alt¤/Del¤ Computer Support 18 09-24-2006 11:41 AM
Bless me Father =?ISO-8859-1?Q?Brian_H=B9=A9?= Computer Support 1 05-24-2004 09:44 PM
Hash::Utils lock_keys Johannes Fürnkranz Perl Misc 5 06-28-2003 03:28 PM



Advertisments