minaevd has asked for the wisdom of the Perl Monks concerning the following question:

Hey there.
Could you explain to me what does the construction below mean?
my %args = @_[0..$#_ + $#_ % 2 - 1];

Thanks in advance.

Replies are listed 'Best First'.
Re: What's the construction?
by BrowserUk (Patriarch) on Sep 15, 2011 at 11:04 UTC

    The math means that it constructs the hash from:

    • all the elements of @_ if there are an even number;
    • all of them except the last one if there are a odd number;
    :
    print "$_ :", $_ + $_ % 2 -1 for 0 .. 11;; 0 : -1 1 : 1 2 : 1 3 : 3 4 : 3 5 : 5 6 : 5 7 : 7 8 : 7 9 : 9 10 : 9 11 : 11

    (Remember the zeroth element!).

    The purpose (I guess) is to avoid the "Odd number of elements in hash assignment" warning,


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: What's the construction?
by halfcountplus (Hermit) on Sep 15, 2011 at 11:06 UTC

    If you assign the values in an array to a hash, they form key-value pairs.

    #!/usr/bin/perl use strict; use warnings FATAL => qw(all); my @ray = qw(a b c d e f); my %hash = @ray[0..3]; while (my ($k, $v) = each (%hash)) { print "$k = $v\n"; }

    So $hash{a} = 'b'. Since I used an array slice (0..3), only the first four elements of @ray were used. You must have an even number of elements in the array you assign to the hash.

    $# is the index of the last element of an array, so the slice in your example makes sure that the array has an even number of elements (the first element is 0, so if the last index is odd, that's an even number of elements, like 0 1 2 3; % is the modulus operator so $#_ % 2 will be 0 if $#_ is even, -1 to make it odd).

    The argument stack to a subroutine is often processed this way so you can do stuff like this:

    someSubRoutine (a => 1, b => 'foo', bar => 6);

    If someSubRoutine() opens with a line like your example, %args is now that hash. This is kind of a nicer way to deal with parameters since you can provide them in any order, and if %args were like this:

    my %args = ( a => 666, b => 'foo', @_ # or the modulus slice );

    Predefine defaults that will be over-ridden, eg, if you pass "a => 999".

      This is kind of a nicer way to deal with parameters since you can provide them in any order...

      While I agree named parameters are nice and, indeed, recommended in some cases by such sources as TheDamian's Perl Best Practices (PBP), this particular approach to named parameters is questionable (in the extreme IMO) because it allows one to arbitrarily add an element to the function argument list (or, in some cases, to drop one) without anyone being the wiser. This sort of 'niceness' has 'accident waiting to happen' and '3AM debug session' written all over it. If there is any valid reason for this particular nicety (and it's hard to imagine one), it should, as pointed out below by Anonymonk, be thoroughly documented – and then should probably be eliminated at the first code review.

Re: What's the construction?
by JavaFan (Canon) on Sep 15, 2011 at 11:37 UTC
    Thanks a lot for the explanation. One more thing to understand. Am I right to say that $# equals to $#_ and means the last index in array?
    You've removed your original post. That makes this thread look very weird for anyone who hasn't looked and remembered your original post.

    As for you question, the answer is no for the first part, and yes for the second. But since you original content is gone, the context is gone, and I cannot explain things further.

Re: What's the construction?
by minaevd (Initiate) on Sep 15, 2011 at 11:34 UTC
    Thanks a lot for the explanation.
    One more thing to understand.

    Am I right to say that $# equals to $#_ and means the last index in array?
      Am I right to say that $# equals to $#_ and means the last index in array?

      $#name means the highest index in the array called @name. So, $#_ is the highest index in the array @_.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
Re: What's the construction?
by Anonymous Monk on Sep 15, 2011 at 13:31 UTC
    This is also an example of code that definitely needs or needed a lot of documentation. And maybe re-coded so that it's even more clear what's going on here. Any bit of source that can't be "instantly and accurately understood," even by a less-experienced person, can be a big maintenance problem that outweighs all well-intended "cleverness."