V
Veli-Pekka Tätilä
Hi,
Being relatively new to Perl with Java and bits of C under my belt, the
newbie questions of a form how do I do or emulate thing T in Perl seem to be
pretty common, and here's yet another one in the same generic spirit as my
earlier thread about interfaces and type safety. If newbie questions like
this have been answered a zillion times already, feel free to point me to
any relevant documents or posts (via Google).
A lengthy intro follos:
I'm new to C+++, too, but remember a number of uses for the const keyword
though the quirky syntax escapes me right now. The first use is telling the
compiler that a pointer passed to a function is const and thus may not be
modified. Put another way, you canot make it point to something else inside
the function and are reminded of any modding attempts at compile time. The
other kind of constness is making the object methods constant and is about
denying the use of methods and operators that would change the state of the
object being passed. You do need to flag the methods const manually but once
this is done all attempts to call any non-const methods are caught right
away. Things like this are called const correctness in the CPP FAQ at:
http://www.parashift.com/c++-faq-lite/const-correctness.html
The first form of constness seems useful in guarding against accidentally
changing a pointer when you, say, ment to dereference it first. This doesn't
appear to be as big an issue as it can be in C. As another example, passing
an array to some analizer function as a constant strongly signals that no
modification of the passed argument should be needed.
A good example of const methods on the OOP side, in my view, is not having
to make a separate String class that cannot be modified. Because Java has no
const methods, there are separate classes for Strings that are constant and
the ones that you can actually modify (excluding the + operator for Strings
as it's not relevant here).
As to what kind of questions these const uses translate to in Perl the
following come to mind.
Is there a way of making:
a. a scalar,
b. an array
c. a hash
d. some reference (e,g. a blessed hash reference)
e. A method
constant inside a function or method?
Some partial solutions of which I'm aware so far:
a to c. you could always pass the parameters by value making it virtually
impossible to modify the originals. However, I'm worried about performance
when huge strings or lists need to be copied around. I reckon I should do
some benchmarks, then.
a and d. Regarding scalars, another approach I've seen involves a reference
to a scalar constant as in:
use strict;
my $goldenRatio = \1.618;
$$goldenRatio *= 2; # Trying to modify a constant.
However, you can still sure modify the reference and I haven't found any
good ways around that, because passing references by value doesn't really
affect matters. You've still got a valid reference to some thingy.
c. The Hash::Util package has got some great functions that let you lock the
key set or the hash as a whole, for example. The functions work very well
but as they aren't built into Perl, there's no way to indicate the constness
of a hash in a prototype, is there. Still locking the hash manually before a
call is quite sufficient, I'm not complaining.
b. Arrays seme like a tough problem as far as constness goes , too. One way
might be to turn the array into a hash and then use the above mentioned hash
utilities to lock it. The PHP style would be numerical indeces denoting the
insertion order as keys and the real array elements as values. Is turning an
array to a locked hash a big performance hit?
Some code follows;
use strict;
use warnings;
use Hash::Util;
my @array = 1 .. 100;
my %hash;
for(my $i = 0; $i < @array; ++$i)
{ # Map array elements to a hash.
$hash{$i} = $array[$i];
} # for
undef @array;
Hash::Util::lock_hash(%hash);
foreach(sort keys %hash)
{ # Try setting all hash values to one.
$hash{$_} = 1; # Fails cleanly.
} # foreach
The problem with this approach is that the values don't retain there order,
unless you use our fake array as a full blown hash and sort the keys. Is
there a better way of doing constant arrays preferrably without lots of
copying involved?
e. I have no idea how to make methods const and guard in some function that
non-const methods are not called. The Java way is to make some sort of
wrapper class that doesn't have any methods that could modify the data in
question. But is there a more elegant solution in object oriented Perl,
perhaps based on dynamic typing?
With kind regards Veli-Pekka Tätilä ([email protected])
Accessibility, game music, synthesizers and programming:
http://www.student.oulu.fi/~vtatila/
Being relatively new to Perl with Java and bits of C under my belt, the
newbie questions of a form how do I do or emulate thing T in Perl seem to be
pretty common, and here's yet another one in the same generic spirit as my
earlier thread about interfaces and type safety. If newbie questions like
this have been answered a zillion times already, feel free to point me to
any relevant documents or posts (via Google).
A lengthy intro follos:
I'm new to C+++, too, but remember a number of uses for the const keyword
though the quirky syntax escapes me right now. The first use is telling the
compiler that a pointer passed to a function is const and thus may not be
modified. Put another way, you canot make it point to something else inside
the function and are reminded of any modding attempts at compile time. The
other kind of constness is making the object methods constant and is about
denying the use of methods and operators that would change the state of the
object being passed. You do need to flag the methods const manually but once
this is done all attempts to call any non-const methods are caught right
away. Things like this are called const correctness in the CPP FAQ at:
http://www.parashift.com/c++-faq-lite/const-correctness.html
The first form of constness seems useful in guarding against accidentally
changing a pointer when you, say, ment to dereference it first. This doesn't
appear to be as big an issue as it can be in C. As another example, passing
an array to some analizer function as a constant strongly signals that no
modification of the passed argument should be needed.
A good example of const methods on the OOP side, in my view, is not having
to make a separate String class that cannot be modified. Because Java has no
const methods, there are separate classes for Strings that are constant and
the ones that you can actually modify (excluding the + operator for Strings
as it's not relevant here).
As to what kind of questions these const uses translate to in Perl the
following come to mind.
Is there a way of making:
a. a scalar,
b. an array
c. a hash
d. some reference (e,g. a blessed hash reference)
e. A method
constant inside a function or method?
Some partial solutions of which I'm aware so far:
a to c. you could always pass the parameters by value making it virtually
impossible to modify the originals. However, I'm worried about performance
when huge strings or lists need to be copied around. I reckon I should do
some benchmarks, then.
a and d. Regarding scalars, another approach I've seen involves a reference
to a scalar constant as in:
use strict;
my $goldenRatio = \1.618;
$$goldenRatio *= 2; # Trying to modify a constant.
However, you can still sure modify the reference and I haven't found any
good ways around that, because passing references by value doesn't really
affect matters. You've still got a valid reference to some thingy.
c. The Hash::Util package has got some great functions that let you lock the
key set or the hash as a whole, for example. The functions work very well
but as they aren't built into Perl, there's no way to indicate the constness
of a hash in a prototype, is there. Still locking the hash manually before a
call is quite sufficient, I'm not complaining.
b. Arrays seme like a tough problem as far as constness goes , too. One way
might be to turn the array into a hash and then use the above mentioned hash
utilities to lock it. The PHP style would be numerical indeces denoting the
insertion order as keys and the real array elements as values. Is turning an
array to a locked hash a big performance hit?
Some code follows;
use strict;
use warnings;
use Hash::Util;
my @array = 1 .. 100;
my %hash;
for(my $i = 0; $i < @array; ++$i)
{ # Map array elements to a hash.
$hash{$i} = $array[$i];
} # for
undef @array;
Hash::Util::lock_hash(%hash);
foreach(sort keys %hash)
{ # Try setting all hash values to one.
$hash{$_} = 1; # Fails cleanly.
} # foreach
The problem with this approach is that the values don't retain there order,
unless you use our fake array as a full blown hash and sort the keys. Is
there a better way of doing constant arrays preferrably without lots of
copying involved?
e. I have no idea how to make methods const and guard in some function that
non-const methods are not called. The Java way is to make some sort of
wrapper class that doesn't have any methods that could modify the data in
question. But is there a more elegant solution in object oriented Perl,
perhaps based on dynamic typing?
With kind regards Veli-Pekka Tätilä ([email protected])
Accessibility, game music, synthesizers and programming:
http://www.student.oulu.fi/~vtatila/