CGI::App to Perl6: param() is now 90% shorter

markjugg on 2006-08-30T02:03:11

Lot's of OO modules have a param() method: CGI::App, HTML::Template, CGI::Session... and they are mostly all about the same. That is, they are a glorifed hash wrapper.

Yet, in Perl5 it's easy for the code for them to be verbose, especiall if you want to accept both a hash /and/ a hashref, and provide some error checking on the input.

The param() method of CGI::App in Perl5 was 33 lines (including some whitespace). The Perl6 translation was 3 lines! This is possible with subroutine signatures and multi-method dispatch. Further, Perl6 tries somewhat successfully to hid e the difference between a hash and hashref, which eliminates another case to check for.

For constrast, here's the two pieces of code:

In Perl5

sub param {
    my $self = shift;
    my (@data) = (@_);

    # First use?  Create new __PARAMS!
    $self->{__PARAMS} = {} unless (exists($self->{__PARAMS}));

    my $rp = $self->{__PARAMS};

    # If data is provided, set it!
    if (scalar(@data)) {
        # Is it a hash, or hash-ref?
        if (ref($data[0]) eq 'HASH') {
            # Make a copy, which augments the existing contents (if any)
            %$rp = (%$rp, %{$data[0]});
        } elsif ((scalar(@data) % 2) == 0) {
            # It appears to be a possible hash (even # of elements)
            %$rp = (%$rp, @data);
        } elsif (scalar(@data) > 1) {
            croak("Odd number of elements passed to param().  Not a valid hash");
        }
    } else {
        # Return the list of param keys if no param is specified.
        return (keys(%$rp));
    }

    # If exactly one parameter was sent to param(), return the value
    if (scalar(@data) <= 2) {
        my $param = $data[0];
        return $rp->{$param};
    }
 
In Perl6
multi method param ()         returns Array { %!params.keys }
multi method param (Str $key) returns Array { @( %!params{$key} ) }
multi method param (%h,*%h)   { %!params = %(%!params, %h); undef }
I think the difference stands for itself...