Reputation: 447
I have the following program in Perl:
use Class::Struct;
use constant {
ACTION => "Action",
TYPE => "Type"
};
struct MyClass => {
&ACTION => '$',
&TYPE => '$'
};
my $obj = new MyObj{
&ACTION => 'add',
&TYPE => '1'
}
# compilation error:
var $action = $obj->&ACTION;
I get a compilation error when trying to access the object field using a constant. Is it possible? What am I doing wrong?
Upvotes: 2
Views: 84
Reputation: 118148
Your code includes some errors such as trying to instantiate MyObj
when all you declared was MyClass
and using var
instead of my
. With those fixed, you'll note that ->&
is a syntax error. See Method Invocation and Method Call Variations.
You can use
That said, here is your code with the corrections to enable it to compile and run:
use strict;
use warnings;
use Class::Struct;
use constant {
ACTION => "Action",
TYPE => "Type"
};
struct MyClass => {
ACTION() => '$',
TYPE() => '$'
};
my $obj = MyClass->new(
ACTION() => 'add',
TYPE() => '1'
);
print $obj->${ \ACTION };
Note that using ACTION()
rather than &ACTION
in the declarations will turn the keys to compile time constants rather than runtime subroutine invocations (prefixing ACTION
with &
tells perl
to ignore the empty prototype, effectively undoing the benefit of use constant
).
It uses the Dereferencing Method Call:
Deferencing Method Call
Perl also lets you use a dereferenced scalar reference in a method call. That's a mouthful, so let's look at some code:
$file->${ \'save' }; $file->${ returns_scalar_ref() }; $file->${ \( returns_scalar() ) }; $file->${ returns_ref_to_sub_ref() };
The code above compiles to $obj->${ \'Action' }
.
As usual, @ikegami spotted something I missed: $x->doesnotexist
is a run-time error. By using constants as method names, it would be possible to detect typos at compile time. For example, if I had made a mistake such as $obj->${ \ACITON };
, the compilation would have failed.
In that case, Const::Fast might provide an aesthetically more pleasing solution (even though it would come at a speed penalty relative to using constant subroutines):
use strict;
use warnings;
use Class::Struct;
use Const::Fast;
const my $ACTION => 'Action';
const my $TYPE => 'Type';
struct MyClass => {
$ACTION => '$',
$TYPE => '$'
};
my $obj = MyClass->new(
$ACTION => 'add',
$TYPE => '1'
);
print $obj->$ACION;
Output:
C:\...\Temp> perl -c tt.pl Global symbol "$ACION" requires explicit package name (did you forget to declare "my $ACION"?) at tt.pl line 21. tt.pl had compilation errors.
That is, such a typo would also be detected at compile time. There is a performance penalty for this over using constant subroutines, but it is less ugly.
Upvotes: 6