Re: trouble with evaluate
by Eliya (Vicar) on Apr 08, 2011 at 19:10 UTC
|
Not sure I understand what you're trying to do. Do you want to retrieve the value of my $var1 or the value of $self->{$var1} (i.e. where the attribute name is in the value of the class variable $var1) ?
The first could be achieved like this
sub get_var{
my ($self, $var_name) = @_;
return eval "\$$var_name";
}
the second like so
sub get_var{
my ($self, $var_name) = @_;
return $self->{eval "\$$var_name"};
}
(As both are methods, you'd need to call them as $val = $obj->get_var('var1').)
Update: here's a full example, so you know how I interpreted your intentions... :)
#!/usr/bin/perl -wl
use strict;
package parser;
my $var1 = "foo";
sub new {
my $self = bless {}, $_[0];
$self->parse();
return $self;
}
sub parse{
my $self = shift;
$self->{$var1} = 'bar';
}
sub get_class_var{
my ($self, $var_name) = @_;
return eval "\$$var_name";
}
sub get_inst_var{
my ($self, $var_name) = @_;
return $self->{eval "\$$var_name"};
}
package main;
my $p = parser->new();
print $p->get_class_var('var1'); # -> foo
print $p->get_inst_var( 'var1'); # -> bar
| [reply] [d/l] [select] |
|
|
Thank you for your help, Eliya . Your comment about class variables vs. instance variables made me realize I was confusing the two. My goal is to create an object that does some work (parses a file) and then persists while other things are happening, and can be queried to get values of any of 50-100 different values that it holds in instance variables. Does that mean that all of those variables should be in the constructor?
I tried both versions of the code you suggested, but they both return "undefined" for $var1, so either the eval {} syntax is not quite right, or $var1 isn't getting set correctly. I'm still trying to figure it out.
| [reply] |
|
|
can be queried to get values of any of 50-100 different values that it holds
I think what you want is actually rather simple. The classic way to store instance data is in the hash that makes up the object ($self here). In other words, as the "variable names" are just keys in the hash (i.e. strings), there's no need for eval or anything like this. Your envisaged generic accessor (get_var) could just do a simple hash lookup:
ackage parser;
sub new {
my $self = bless {}, $_[0];
$self->parse();
return $self;
}
sub parse{
my $self = shift;
$self->{var1} = 'foo';
$self->{var2} = 'bar';
#...
}
sub get_var{
my ($self, $var_name) = @_;
return $self->{$var_name};
}
package main;
my $p = parser->new();
print $p->get_var('var1'); # -> foo
print $p->get_var('var2'); # -> bar
(note that ->parse() doesn't necessarily have to be called from the constructor) | [reply] [d/l] [select] |
|
|
Does that mean that all of those variables should be in the constructor?
No.
| [reply] |
Re: trouble with evaluate
by GrandFather (Saint) on Apr 09, 2011 at 02:44 UTC
|
use strict;
use warnings;
package Parser;
sub new {
my ($class, %params) = @_;
return bless \%params, $class;
}
sub parse {
my ($self, $inFile) = @_;
while (<$inFile>) {
chomp;
my ($var, $value) = split;
$self->{$var} = $value;
}
}
sub getVar {
my ($self, $varName) = @_;
return $self->haveVar ($varName) ? $self->{$varName} : undef;
}
sub haveVar {
my ($self, $varName) = @_;
return exists $self->{$varName};
}
package main;
my $parser = Parser->new ();
$parser->parse (*DATA);
print "var1 = ", $parser->getVar ('var1') if $parser->haveVar ('var1')
+;
__DATA__
var1 wibble
var2 plonk
var4 dibbly
Prints:
var1 = wibble
True laziness is hard work
| [reply] [d/l] [select] |
|
|
Thank you! You guys are really amazing. I think your approach is basically the same as what sundialsvc4 was suggesting. I'm still struggling to grasp how Perl objects work. JavaFan wrote "A Perl object is a reference that's blessed into a package", and if I understand your code right, the reference in this case is to the hash that contains the parameters ("bless \%params, $class"). I agree that what I'm trying to do is trivial, but I am none the wiser about why none of the other versions suggested worked, except that the evaluation of the passed variable name was problematic.
| [reply] |
|
|
Perl objects are a reference to something (hash, scalar, array, code, ... - it doesn't much matter what) with a little magic stirred in. See Not quite an OO tutorial for a light weight introduction to Perl OO.
The trap in Perl is that, without strictures (use strict; use warnings; - which you should always use btw.) you can do some pretty hairy stuff that looks like it might be fine and just what you want to do, but is really full of nasty lurking traps. The nasty thing that most often looks ok is called "symbolic references" where you use the contents of a variable to access another variable by name. Pretty much always you can replace the referenced variable by a hash element where the variable name is the key to the hash.
For the task at hand it is convenient to turn the hash into an object that knows how to parse an input file (or whatever) and provides convenient access to the parsed variables. This is a pretty light weight use of OO, but it is likely to provide significant payback if you need to add value to the data, like combining the values of actual variables into pseudo variables which can be accessed just like the actual variables.
True laziness is hard work
| [reply] |
|
|
... I am none the wiser about why none of the other versions suggested worked ...
genghis: You might get even more and better help and make more headway if, when you say something like "it didn't work", you would also give the other monks a small, self-contained, runnable example of the "it" in question, along with input and expected output. The very process of putting together such an example can often provide you great enlightenment.
| [reply] |
Re: trouble with evaluate
by wind (Priest) on Apr 08, 2011 at 18:41 UTC
|
Assuming you have use strict on like you should...
Then the following would allow you to access package variables declared with our (not with my).
our $var1;
our $var2;
sub get_var{
my ($self, $var_name) = @_;
no strict 'refs';
return ${"$var_name"};
}
I'm really not sure why you would want to do that though. | [reply] [d/l] |
|
|
| [reply] |
|
|
What "dire warnings" about using our?
Also, you claim that the below parse function works. How does it actually "work"? What do you believe that you're saving in $self->{$var1} and how are you planning on using it?
my $var1;
my $var2;
my $var3;
#set values -- this part works
sub parse{
...
$self->{$var1} = 'a';
$self->{$var2} = 'b';
$self->{$var3} = 'c';
...
}
If you're doing true Object Oriented programming, I believe that what you truly want is just the following
package parser;
...
# Some constructor here
...
#set values -- this part works
sub parse{
...
$self->{var1} = 'a';
$self->{var2} = 'b';
$self->{var3} = 'c';
...
}
sub get_var{
my ($self, $var_name) = @_;
return $self->{$var_name};
}
| [reply] [d/l] [select] |
|
|
|
|
Re: trouble with evaluate
by locked_user sundialsvc4 (Abbot) on Apr 08, 2011 at 23:22 UTC
|
Basically, it sounds like you’re asking for a slight twist on “accessors.” A Perl object is basically just a hash. You can, therefore, obtain values from it that way. (And yes, as you plan to do, “the object itself” should be the one that knows how to do this, and who checks for incorrect or nonsensical requests.)
Lately, I’ve gotten into the habit of putting “variables like these” into a separate hash, which is part of the object instance and with a name like, say, localvars. These (and only these) are the values which are supposed to be accessible to routines like the ones you describe, and, since they’re now neatly in just one place, it’s easy to check them (and to Data::Dumper dump them). It makes it really obvious that “you’re not supposed to just be grabbin’ any-old-key ... only one of these.” And it’s easy to (Carp) confess if the name is wrong.
$self->{'localvars'}->{$var_name} ...
| |
|
|
A Perl object is basically just a hash.
No, it's not. A Perl object is a reference that's blessed into a package. A hash isn't a reference. And while it's true many Perl objects are hashreferences, that's not the only way to create an object.
| [reply] |