develooper Front page | perl.perl5.porters | Postings from July 2013

Re: key/value hash slices summary

Thread Previous | Thread Next
From:
Ruslan Zakirov
Date:
July 13, 2013 20:37
Subject:
Re: key/value hash slices summary
Message ID:
CAMOxC8viCAmOUUExw8vmAPaXoU8C0Cip8uaLFRSZJikJEbthEQ@mail.gmail.com
Hi,

Thank you for all feedback. I've updated behavior with lvalue functions,
added more tests and implemented de-parsing. Summary has been updated as
well and you can read it below.

So far there are two things that puzzle me:

* `delete %hash{ qw(...) }` is not allowed. However, I think it can be very
handy to be able to split a hash into two. Once this door is open then
`delete local ...` is also should be supported, but just local is not
supported and I don't think it should be. At this moment I prefer delete to
be banned for key/value slices.

* lvalue functions. I think that returning a key/value slice from a lvalue
function should be fatal, even if function is called as RHS.

Opinions?


Summary:

Key/value hash slices and index/value array slices
  Syntax
    Just like existing slice operations.

        my %sub = %hash{'a', 'b', 'c'};

  Why a new syntax?
    New syntax fits within existing syntax for slices and completes the
    picture.

        my $scalar = $h{'a'};
        my @list = @h{'a', 'b'};
        my %hash = %h{'a', 'b'};

    First two from above exist for ages, the third fits natural. I don't see
    any other reasonable behaviour for the third.

  Why not a function?
        my %second = slice %first, qw/a c/;

    It's sure possible to implement this as function, but I feel it fits.

  But Perl 6?
    Sigils in Perl 6 have different meaninging and it's radical change from
    Perl 5, so this argument is hardly applicable..

  Not existing keys
    If a key doesn't exist then undef is returned. However, it doesn't
    create a new record in the source.

        my %first = (a => 1, b => 2);
        my %second = %first{qw/a c/};

    Entry with "c" key exists in %second and its value is "undef". It's very
    easy to skip not existing keys:

        my %second = %first{ grep exists $first{$_}, qw/a c/ };

    Behaviour is consistent with existing slices and other operations.

  Repeated keys
    You get what you asked for, so the following has repeated results:

        @a = %h{ ('c') x 3 };

  Hash refereces
    Nothing suprising here, the following constructs work:

        %$h{'c','d','e'}
        %{$h}{'c','d','e'}

  Scalar context
    Operator returns list, so in scalar context last value is used.

        my $e = %h{ "foo", "bar" };

    Above is "equivalent" of "$e = $h{'bar'}".

    By luck the following "red eyes mistake" result in what most people
    expect:

        my $s = %hash{'a'};

  Interpolation in strings
    "%" is not treated specially in strings, so key value slices are not
    interpolated in any way.

  Left value
    Most explicit lvalue operations on key/value hash slices throw errors:

        %h{qw(a b)} = qw(A B);

    Even:

        %h{'a'} = 'foo';

    Above is not scalar assignment as left hand side is a list, so it's also
    fatal.

    This also means that operation can not be used as result of lvalue sub.

    Exceptions are grep, map, foreach operations as the following should
    behave similar, even if it's questionable:

        $_++ for %hash;
        $_++ for %hash{'a', 'b'};

  Taking reference
        @a = \%h{ qw'c d e' };
        @a = \( %h{ qw'c d e' } );

    Above behave in the same way and produce list of references. "keys" are
    not aliased, so changing them doesn't affect source hash.

  Warnings
    *
            Scalar value %h{i} better written as $h{i}

        Can be workarounded.

  Errors
    *   Localizing hash slices is not allowed, the following fails:

            local %h{qw/a b/};

    *   You can not use these slices as left hand side of assignment op:

            %h{'a', 'b'} = qw(A B);
            %h{'a'} = 'value';

    *   delete is not allowed, the following fails:

            my %sub = delete %hash{'a', 'b'};

        So far above code dies and suggests to use hash slice, but it can be
        re-considered.

  Off topics
   pushing into a hash
    It's been brought up a few times that it would be cool to get syntax to
    push values into a hash. The following syntax looks good:

        push %hash, ...;
        push %hash, %other;
        push %hash, @pairs;

    Also, it was mentioned that it would be cool to optimize the following
    using new push functionality:

        %h = (%h, ...)


-- 
Best regards, Ruslan.


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About