If I have some hash with the (absolutely) static set of keys, can I avoid calculating of hash functions on each access to elements of this hash by key at run time?
Say, I have a static associative array %saa
with the keys:
my %saa = (
A => "aaa",
B => "bbb",
C => "ccc"
);
How to pre-calculate hash function values for these keys in compile time and use it in run time in such effective manner as I did when using indexed access to simple lists elements.
As I know for now, in perl5 it may be implemented only as emulation of hashes using lists (use constant A=>0, B=>1...; $saa[A]="ddd"
).
Maybe there is more straightforward way to implement static associative arrays (also called "named tuples", not hashes) in Perl ?
For example, that's how the desired feature was implemented in Crystal language.
The closest thing to the functionality described in struct NamedTuple(**T)
is Const::Fast
.
#!/usr/bin/env perl
use strict;
use warnings;
use Const::Fast qw( const );
my %language;
BEGIN {
const %language => (
name =>'Crystal',
year => '2011',
);
}
print "$language{$_}\n" for qw( name year other );
$ perl t.pl
Crystal
2011
Attempt to access disallowed key 'other' in a restricted hash at t.pl line 17.
BUT the check happens at run time. See Neil Bowers' excellent review for performance information. The stats may have changed since then, but it should give you an idea.
An alternative is not to use hashes at all, but use Class::XSAccessor to define a simple class:
#!/usr/bin/env perl
use strict;
use warnings;
package My::Language;
use Class::XSAccessor (
constructor => 'new',
getters => {
name => 'name',
year => 'year',
},
);
package main;
my $language;
BEGIN {
$language = My::Language->new(
name =>'Crystal',
year => '2011',
);
}
print $language->$_, "\n" for qw( name year other );
Class::XSAccessor::Array
should be about 10%-15% faster:
#!/usr/bin/env perl
use strict;
use warnings;
package My::Language;
use Class::XSAccessor::Array (
getters => {
name => 0,
year => 1,
},
);
package main;
my $language;
BEGIN {
$language = bless ['Crystal', '2011'] => 'My::Language';
}
print $language->$_, "\n" for qw( name year other );
In all cases, the checks happen at run time.