in reply to [Perl 6] List of length 2 or...

I don't know about Perl 6, but I don't see any reason for the reference judo here.

my %h = map { chomp; (split /\s+/, $_, 2)[0,1] } <DATA>; print Dumper \%h; __DATA__ two 2 one three 3 X

Output:

$VAR1 = { 'three' => '3 X', 'one' => undef, 'two' => '2' };

But then, I probably also wouldn't use map to loop over a reading filehandle this way either. I don't think the brevity quite justifies reading the whole file before processing.

Update: And if you want to add in default values, another map would make that explicit easier than adding more into the one loop.

my %h = map { defined ? $_ : $default } map { chomp; (split /\s+/, $_, 2)[0,1] } <DATA>;

Replies are listed 'Best First'.
Re^2: [Perl 6] List of length 2 or...
by blazar (Canon) on Oct 23, 2008 at 18:29 UTC
    I don't know about Perl 6, but I don't see any reason for the reference judo here.

    No good reason but the obvious one that it just didn't occur to me! I only see a problem with it: it works nicely or at least in accordance with my own chosen example when one value is missing from a line, but when two are then I get both

    • a warning under warnings;
    • an empty key associated with an undef value.

    See?

    aleph:~ [19:27:57]$ perl -wMData::Dumper -e 'print Dumper {undef() => +undef}' Use of uninitialized value in anonymous hash ({}) at -e line 1. $VAR1 = { '' => undef };

    I don't see any equally elegant and simple way to get rid of those. So we're somewhat back to my point...

    Again, I was also about to ask you, just to destroy the missing-one-value-only case too: what if undef were not the default value I wanted? (Actually, you won't believe it but just before posting the root node, the default value in my code was 0 and only before pressing the button did I change it to undef which I thought was better suited for a generic example.) But I see that you thought of it yourself:

    my %h = map { defined ? $_ : $default } map { chomp; (split /\s+/, $_, 2)[0,1] } <DATA>;

    in this respect I must say that whenever I see or think of chained maps and greps I feel discomfortable with them even if they're aesthetically appealing and convert them to either a single map if at least one is present in the chain or to a single grep (theorically: I have yet to see an actual chain of greps...) In fact, I don't know whether the multiple loops they implicitly perform are actually optimized to a single one: this would certainly be easy when the mapping is 1-1 but not quite so in the general case... But often it is, if the operation is performed by a human as in this case and perhaps this may be the way to go:

    my %pairs = map { chomp; my($k,$v)=(split ' ', $_, 2)[0,1]; defined $k ? ($k => $v // $default) : () } <DATA>;

    At least, this is clear enough for a human to read. Otherwise another solution that I'm pasting here just for fun and still playing with references is:

    my %pairs = map { chomp; map @{ ([], [@$_, $default], $_)[scalar @$_] }, [split ' ', $_, 2] } <DATA>;

    Here, what bothers me most is the long scalar thingie, but Perl had to resolve the possibly ambiguous (LIST)[EXPR] expression and it did so by always assuming it's a list slice. Of course, I may use [0+@$_] but that would make me feel like I were playing golf, which is not the case now... But of course, it would be different if we were under Perl 6 and a single plus forcing numeric context would suffice: then again, if we were then we would be doing something entirely different to start with, so end of the story!

    To put it briefly, as far as I'm concerned, it would be best for me if there were some syntax available that would enable working with lists without enclosing them in references, making my last solution both more aesthetically appealing, intuitive, comprehensible, and avoiding the referencing / dereferencing madness...

    But then, I probably also wouldn't use map to loop over a reading filehandle this way either. I don't think the brevity quite justifies reading the whole file before processing.

    Actually, I specified in the node in which I (seriously) suggested the technique for the first time that it had sense because the file would have been processed as whole anyway. Of course, it's still not exactly the same thing, and it is only sensible a thing to do if it's reasonably sized. Since we're talking about Perl 6 here, it is worth reminding that it would be different if we had lazy list evaluation by default, as it actually has.

    --
    If you can't understand the incipit, then please check the IPB Campaign.