Making Datatypes Constant and Emulating Const Correctness

Discussion in 'Perl Misc' started by Veli-Pekka Tätilä, Aug 25, 2005.

  1. 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:

    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;

    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ä ()
    Accessibility, game music, synthesizers and programming:
    Veli-Pekka Tätilä, Aug 25, 2005
    1. Advertisements

  2. <snip>


    use constant TEST1 => 42;
    use constant TEST2 => ( 12, 34 );
    use constant TEST3 => { item1 => 23 };
    use constant TEST4 => sub { return 56 };

    print TEST1."\n";
    print join " ",TEST2,"\n";
    print TEST3->{item1}."\n";
    print TEST4->()."\n";

    You could build these dynamically at runtime using eval, though this
    probably wouldn't gain you anything.

    not sure about e. though.

    Mark Clements, Aug 25, 2005
    1. Advertisements

    Hash: SHA1

    use Readonly;

    # a. Scalar:
    Readonly $foo => 'Copyright 2005 by Sue D. Nymme';

    # b. Array:
    Readonly @bar => ('Harry', 'Hermione', 'Ronald');

    # c. Hash:
    Readonly %baz => {Bush => 'President', Cheney => 'Vice President'};

    d. A reference is just a scalar. A referent is that to which the
    reference points. A reference can be made Readonly, but that's not
    usually very useful. If the referent is a scalar, array, or hash,
    it can be made Readonly.

    e. I'm not sure what you mean.

    - --
    Version: GnuPG v1.2.5 (MingW32) - WinPT 0.7.96rc1

    -----END PGP SIGNATURE-----
    Eric J. Roode, Aug 27, 2005
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.