Perl object, toString output from within module - perl

I'm doing a class assignment to learn about Object Oriented programming in Perl. I've got a real basic class that looks like this.
sub new{
my $class = shift;
my $self = {
'Sides' => 3,
'SL' => \#sidelengths};
bless $self, $class;
return $self;
}
I've got two modules to change the sides and length(can't figure out how to modify the sidelegnths with an accessor though) but I have a requirement for my work that I have a method like this
"a method: toString() which returns all of the file attributes in a printable
string. If this is done correctly, the PERL
print $file->toString() . "\n";
should print a readable summary of the file."
I already think I want to use Data::Dumper to do this and that works within a script but it sounds like I need to use it within a module and call that to print a string of whats in the object. So far I have this
sub toString{
my $self = #_;
Dumper( $self );
}
Which just prints out "$VAR1 = 1"

What you want here is to shift an argument out of #_.
sub toString {
my $self = shift #_;
Dumper( $self );
}
When you have $var = #array, that evaluates the array in a scalar context, and that returns the number of elements in the array. So, your statement my $self = #_; set $self to the number of arguments passed to toString, which in this case was 1. (The $self argument.)
Alternately, you can capture the first element of #_ this way:
sub toString {
my ($self) = #_;
Dumper( $self );
}
What this does is evaluate #_ in list context since it uses list assignment. It assigns the first element of #_ to $self.

my $self = #_;
is a scalar assignment operator, so it #_ in scalar context, which is the number of elements it contains. You want to use the list assignment operator.
sub toString {
my ($self) = #_;
return Dumper( $self );
}

Related

Not a code reference in Perl class

I'm stumped. I'm new to Perl and after reading some articles, I still can't figure this one out. It's a very small class.
package Haha;
sub new {
$class = shift;
$self = {
path => shift
};
bless $self, $class;
return $self;
}
sub setPath {
my ($self, $new_path) = shift;
$self->(path) = $new_path if defined $new_path;
return $self->(path);
}
sub getPath {
my $self = shift;
return $self->(path);
}
1;
And I used it like this:
use lib 'lib';
use Haha;
my $new_excel = new Haha("sample path");
print $new_excel->getPath() ;
<>;
Class Haha line 23 raises the "Not a code reference" error.
The line that says return $self->(path);
Your class (like most Perl classes) is implemented on top of hashes. When you create a new object in your constructor, you do it like this:
sub new {
$class = shift;
$self = {
path => shift
};
bless $self, $class;
return $self;
}
The line $self = { ... } creates an anonymous hash and stores a reference to that hash in $self. So, $self is a hash reference. Which means that you should access its contents using hash syntax. So your accessor and mutator methods are wrong.
sub setPath {
my ($self, $new_path) = shift;
$self->(path) = $new_path if defined $new_path;
return $self->(path);
}
You are using parentheses, not braces, to access the path value in your hash. The line:
$self->(path) = $new_path if defined $new_path;
Should be:
# Note: braces, not parentheses
$self->{path} = $new_path if defined $new_path;
And the line:
return $self->(path);
Should be:
# Note: braces, not parentheses
return $self->{path};
You need to make a similar fix to getPath().
Unfortunately, the syntax $reference->($value) is completely valid. It means "call the subroutine that you have a reference to in $reference, passing it $value". But, of course, this requires $reference to contain a subroutine reference, not a hash reference.
A few other suggestions.
Always use strict and use warnings.
Indirect object notation ($new_excel = new Haha("sample path")) is likely to burn you at some point. Please use $new_excel = Haha->new("sample path") instead.
Your line my ($self, $new_path) = shift doesn't do what you think it does. You want my ($self, $new_path) = #_.
path is an attribute of the object, use curly brackets:
sub getPath {
my $self = shift;
return $self->{path};
}
In the sub setPath, the variable $new_path is never assigned, use instead:
sub setPath {
my ($self, $new_path) = #_;
$self->{path} = $new_path if defined $new_path;
return $self->{path};
}

Object Oriented In Perl Script

sub new
{
my $class = shift; #off the first element
my $self = { };
bless $self, $class;
return $self;
}
Could anyone explain that? What is the use of the following three lines of code?
my $self = { };
bless $self, $class;
return $self;
my $self = { }; creates an anonymous hash reference and stores it in the lexical variable $self.
bless $self, $class; tells Perl that $self is not just any reference but actually an object of the class stored in $class. See bless in perldoc. bless $x, $y returns $x, and a subroutine always returns the value of the last executed statement unless explicetly told otherwise with a return statement, so the next line is optional, but good for readability.
return $self; hands the value in $self (our special object reference) back to the calling function. See return in perldoc.
Edit:
To clarify, if you don't bless your reference, you won't be able to call methods on it. With bless you tell Perl, "look, from now on, associate the reference in $self with the class in $class, so that I can use the methods in that class on the reference."

Getting issues in object oriented perl

I am new to OO perl. I am trying to write one simple program but getting the error.
Created a package Employee.pm as
package Employee;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub get_names {
my $self = #_;
print " getting the names \n";
return $self;
}
sub set_names {
my ($self, $last_name) = #_;
$self->{last_name} = $last_name;
return $self->{$last_name};
}
1;
And created a .pl file as
use strict;
use warnings;
use Employee;
my $obj = new Employee("name" => "nitesh", "last_name" => "Goyal");
my $val = $obj->get_names();
print %$val;
my $setName = $obj->set_names("kumar");
print "$setName \n";
I am getting error as
"Can't use string ("1") as a HASH ref while "strict refs" in use at class1.txt line 10."
The error
"Can't use string ("1") as a HASH ref ..
Comes from this part:
sub get_names {
my $self = #_;
When an array is put in scalar context, it returns its size. Since you call the sub with
$obj->get_names();
Only one argument is passed, which is the object, so #_ contains 1 argument, and its size is 1, therefore in the sub get_names, the variable $self is set to 1. Hence the error. What you probably should do is
my $self = shift;
But then, that will not do anything, because you never stored the names in your constructor. As mpapec said, you should do
my $self = { #_ };
in the constructor sub new.
Also, in get_names, you simply return the object, which is not very useful. You should perhaps return $self->{name} and $self->{last_name}.

How to make "universal" getters and setters in an object in perl?

How do you make one setter method, and one getter method to manage access to fields of an object? The new subroutine looks like this:
sub new {
my $class = shift;
my $self = {#_};
bless($self,$class); # turns this into an object
}
Creation of a new object looks like this:
$foo = Package::new("Package",
"bar", $currentBar,
"baz", $currentBaz,
);
This is not a good idea.
Perl instituted the use of use strict; to take care of problems like this:
$employee_name = "Bob";
print "The name of the employee is $employeeName\n";
Mistyped variable names were a common problem. Using use strict; forces you to declare your variable, so errors like this can be caught at compile time.
However, hash keys and hash references remove this protection. Thus:
my $employee[0] = {}
$employee[0]->{NAME} = "Bob";
print "The name of the employee is " . $employee[0]->{name} . "\n";
One of the reasons to use objects when you start talking about complex data structures is to prevent these types of errors:
my $employee = Employee->new;
$employee->name("Bob");
print "The name of the employee is " . $employee->Name . "\n";
This error will get caught because the method name is name and not Name.
Allowing users to create their own methods at random removes the very protection we get by using objects:
my $employee = Employee->new;
$employee->name("Bob"); #Automatic Setter/Getter
print "The name of the employee is " . $employee->Name . "\n"; #Automatic Setter/Getter
Now, because of automatic setters and getters, we fail to catch the error because any method the user names is valid -- even if that user made a mistake.
In fact, I setup my objects so my object doesn't necessarily know how it's structured. Observe the following class with methods foo and bar:
sub new {
my $class = shift;
my $foo = shift;
my $bar = shift;
my $self = {};
bless $self, $class;
$self->foo($foo);
$self->bar($bar);
return $self;
}
sub foo {
my $self = shift;
my $foo = shift;
my $method_key = "FOO_FOO_FOO_BARRU";
if (defined $foo) {
$self->{$method_key} = $foo;
}
return $self->{$method_key};
}
sub bar {
my $self = shift;
my $bar = shift;
my $method_key = "BAR_BAR_BAR_BANNEL";
if (defined $bar) {
$self->{$method_key} = $bar;
}
return $self->{$method_key};
}
I can set the class values for foo and bar in my constructor. However, my constructor doesn't know how those values are stored. It simply creates the object and passes it along to my getter/setter methods. Nor, do my two methods know how they store each other's value. That's why I can have such crazy names for my method's hash keys because that is only available in the method and no where else.
Instead, my methods foo and bar are both setters and getters. If I give them a value for foo or bar, that value is set. Otherwise, I simply return the current value.
However, I'm sure you already know all of this and will insist this must be done. Very well...
One way of handling what you want to do is to create an AUTOLOAD subroutine. The AUTOLOAD subroutine automatically is called when there's no other method subroutine by that name. The $AUTOLOAD contains the class and method called. You can use this to setup your own values.
Here's my test program. I use two methods bar and foo, but I could use any methods I like and it would still work fine
One change, I use a parameter hash in my constructor instead of a list of values. No real difference except this is considered the modern way, and I just want to be consistent with what everyone else does.
Also notice that I normalize my method names to all lowercase. That way $object->Foo, $object->foo, and $object-FOO are all the same method. This way, I at least eliminate capitalization errors.
use strict;
use warnings;
use feature qw(say);
use Data::Dumper;
my $object = Foo->new({ -bar => "BAR_BAR",
-foo => "FOO_FOO",
}
);
say "Foo: " . $object->foo;
say "Bar: " . $object->bar;
$object->bar("barfu");
say "Bar: " . $object->bar;
say Dumper $object;
package Foo;
sub new {
my $class = shift;
my $param_ref = shift;
my $self = {};
bless $self, $class;
foreach my $key (keys %{$param_ref}) {
# May or may not be a leading dash or dashes: Remove them
(my $method = $key) =~ s/^-+//;
$self->{$method} = $param_ref->{$key};
}
return $self;
}
sub AUTOLOAD {
my $self = shift;
my $value = shift;
our $AUTOLOAD;
( my $method = lc $AUTOLOAD ) =~ s/.*:://;
if ($value) {
$self->{$method} = $value;
}
return $self->{$method};
}
Something like this...
sub get {
my $self = shift;
my $field = shift;
return $self->{$field};
}
sub set {
my $self = shift;
my $field = shift;
$self->{$field} = shift;
}
...makes it possible to write
$obj->set(foo => 'my foo value');
print $obj->get('foo');
But nowadays, it is very common to just use Moose.

returning a lazily-computed scalar, in perl

I'm trying to add some functionality to our code base by using tied scalars.
We have a function which is specified to return scalars. I thought I could add some features to the system by tie-ing these scalars before returning them, but it looks like the FETCH method is called just before the return, which results in an untied scalar being returned.
Is there any way around this?
I really want to keep the subroutine's interface (returning scalars) intact if it's at all possible.
use strict;
use warnings;
main();
sub GetThing{
my $thing;
tie $thing, 'mything', #_;
return $thing;
}
sub main {
my %m;
$m{pre} = GetThing('Fred');
print "1\n";
print $m{pre};
print "2\n";
print $m{pre};
print "3\n";
}
package mything;
require Tie::Scalar;
my #ISA = qw(Tie::StdScalar);
sub TIESCALAR {
my $class = shift;
bless {
name => shift || 'noname',
}, $class;
}
sub FETCH {
my $self = shift;
print "ACCESS ALERT!\n";
return " NAME: '$self->{name}'\n";
}
Desired output:
1
ACCESS ALERT!
NAME: 'Fred'
2
ACCESS ALERT!
NAME: 'Fred'
3
I can get the desired output by returning a reference, and dereferencing on each access, but that ruins our established interface, and makes it more confusing for our users.
--Buck
As DVK said, tie applies to containers, so isn't useful for returned values.
For that, you use overloading. An example (not all the possible overloaded operations are supplied; see http://perldoc.perl.org/overload.html#Minimal-set-of-overloaded-operations):
use strict;
use warnings;
main();
sub GetThing{
my $thing;
$thing = "mything"->new(#_);
return $thing;
}
sub main {
my %m;
$m{pre} = GetThing('Fred');
print "1\n";
print $m{pre};
print "2\n";
print $m{pre};
print "3\n";
}
package mything;
use overload 'fallback' => 1, '""' => 'FETCH';
sub new {
my $class = shift;
bless {
name => shift || 'noname',
}, $class;
}
sub FETCH {
my $self = shift;
print "ACCESS ALERT!\n";
return " NAME: '$self->{name}'\n";
}
As mentioned in other answers, tie applies to containers, and not to values, so there is no way to assign a tied variable to another variable and retain the tied properties.
Since assignment is out, you need to pass the container into the GetThing routine. You can do this by reference as follows:
use strict;
use warnings;
main();
sub GetThing{
tie ${$_[1]}, 'mything', $_[0];
}
sub main {
my %m;
GetThing('Fred' => \$m{pre});
print "1\n";
print $m{pre};
print "2\n";
print $m{pre};
print "3\n";
}
package mything;
require Tie::Scalar;
my #ISA = qw(Tie::StdScalar);
sub TIESCALAR {
my $class = shift;
bless {
name => shift || 'noname',
}, $class;
}
sub FETCH {
my $self = shift;
print "ACCESS ALERT!\n";
return " NAME: '$self->{name}'\n";
}
which produces the correct output.
However, if you want to retain the assignment, you will need to use overloading, which applies to values (actually to objects, but they themselves are values). Without more detail on your intended purpose it is hard to give a complete answer, but this will meet your stated requirements:
use strict;
use warnings;
main();
sub GetThing{
return mything->new( shift );
}
sub main {
my %m;
$m{pre} = GetThing('Fred');
print "1\n";
print $m{pre};
print "2\n";
print $m{pre};
print "3\n";
}
package mything;
sub new {
my $class = shift;
bless {
name => shift || 'noname',
}, $class;
}
use overload '""' => sub { # '""' means to overload stringification
my $self = shift;
print "ACCESS ALERT!\n";
return " NAME: '$self->{name}'\n";
};
Both ties and overloads can get complicated, so read through all of the documentation if anything is not clear.
First, the exact method of doing what you are proposing seems technically impossible:
Tied variables have the tie attached to the variable itself, not to its value.
In Perl, subroutine's return values are returned by value, meaning you take the value passed to return, access it (in you case, accessing the tied variable and calling FETCH in the process) - and then copy that value! Which means that what the caller gets is a scalar VALUE, not a scalar variable (tied or untied).
Your confusion, in short, seems to stem from mixing together variables (locations in program's symbol table) and values stored in those variables.
Second, you were somewhat unclear as to what exactly you are trying to achieve, so it's hard to propose how to achieve what you want. But assuming, based on your description, that you wanted to call some method upon subroutine's return (possibly passing it the return value), you CAN do that.
To do so, you need to employ what fancy people call aspect programming. The politically (and technically) correct way of doing it in Perl is by using Moose.
However, you can DIY it, by basically replacing the original method with a wrapper method.
The exact mechanics of both Moose and DIY approaches can be seen in the first two answers to the following SO question, so I won't copy/paste them here, hope you don't mind:
Simulating aspects of static-typing in a duck-typed language
If you're feeling adventurous, you could also use the Scalar::Defer module which provides a general-purpose mechanism for a scalar variable to compute a value lazily, either once or on each access.