Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

[Perl6] Slurpy array of named arguments?

by ctilmes (Vicar)
on Dec 05, 2016 at 09:16 UTC ( #1177215=perlquestion: print w/replies, xml ) Need Help??

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

I can ask for a slurpy hash of named arguments with '*%args', or a slurpy array of non-named arguments with '*@args', but I want an ordered list of Pairs (specified with 'name => value'). Is there a good way to get that?
class testing { method newhash(*%args) { for %args.kv -> $k, $v { say "Hash Key $k => Value $v"; } } method newarray(*@args) { for @args -> $k, $v { say "Array Key $k => Value $v"; } } } my $x = testing.newhash(a => 1, b => 2); # Messes with specified ord +er my $y = testing.newarray(c => 3, d => 4); # Looks good, but doesn't w +ork my $z = testing.newarray('e', 5, 'f', 6); # Works, but ugly
Hash Key b => Value 2 Hash Key a => Value 1 Array Key e => Value 5 Array Key f => Value 6

Replies are listed 'Best First'.
Re: [Perl6] Slurpy array of named arguments?
by TheDamian (Priest) on Dec 05, 2016 at 14:24 UTC

    The problem is that, in the argument list of a sub or method, any key => 'value' pair with an unquoted key is always treated as a named argument. So any such argument it is always routed into the slurpy hash, and never into the slurpy array.

    The simplest solution is to quote the key of each pair, in which case they will be treated as positional arguments and will be routed into the slurpy array.

    Of course, each such positional pair will be a single Pair object (not a flattened list of key, value) so you will end up with an array of pairs, not an array of alternating keys and values. That means you'll need to unpack them differently in the for loop.

    Putting all that together, we get:

    class testing { method newhash(*%args) { for %args.kv -> $k, $v { say "Hash Key $k => Value $v"; } } method newarray(*@args) { for @args».kv -> [$k, $v] { say "Array Key $k => Value $v"; } } } my $x = testing.newhash(a => 1, b => 2); # Messes with specified +order my $y = testing.newarray('c' => 3, 'd' => 4); # Looks okay, and work +s

    If you simply must have unquoted keys, then you'll need to pass an explicit list of them (in parens), because the "unquoted-means-named" magic only applies at the outermost level (known as the "comma level") of the argument list. So, with the rewritten newarray method above, the following would also work:

    my $y = testing.newarray((c => 3, d => 4)); # Looks okay, and works
Re: [Perl6] Slurpy array of named arguments?
by alexander_lunev (Pilgrim) on Dec 05, 2016 at 14:13 UTC

    It seems that you can't do that other than sorting keys:

    class testing { method newhash(*%args) { for %args.sort(*.key)>>.kv -> ($k, $v) { say "Hash Key $k => Value $v"; } %args.perl.say; } } my $x = testing.newhash(a => 1, b => 2, c => 3, d => 4);

    Here's what docs.perl6.org says about it:

    Looping over hash keys and values

    Note that the order of the keys and values printed cannot be relied upon; the elements of a hash are not always stored the same way in memory for different runs of the same program. Sometimes one wishes to process the elements sorted on, e.g. the keys of the hash.

    There you can also find canonical example.

    The code %args.perl.say also do keys sorting, no magic there either.

    It seems to me you have only one way to put your keys in order - name them in sortable manner and sort it later.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1177215]
Approved by marto
Front-paged by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2021-09-17 20:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?