in reply to Re: Print something when key does not exist
in thread Print something when key does not exist

Hello Ken, I can't thank you enough for the time and effort spent on such detailed and fantastic analysis. This is your second answer to my two posts here on perl monks and I can say for sure that I have learnt so much from your answers than I could ever have by reading a book.

In regards to my use of hash reference instead of hash was basically to get a hang of hash reference iteration. I have been reading references lately and thought would be a good idea to practice it here.

Your following points were extremely valuable and helpful:

- #!/usr/bin/env perl -l for new lines - Using my ($name, $code, $count) = split /\Q$sep/; instead of array and hard coding separator - my @codes = sort keys %codes_found; Instead of looping through the hash - Using for instead of foreach - print join $sep => $name, map { $data{$name}{$_} || '' } @codes; Thi +s is exactly what I was looking for. Idiomatic and very readable.

One follow up question, I never seen fat comma (=>) used in join. Is this because we wanted the $sep to be quoted and fat comma will do that for us?

Also, in the line

print join $sep => $name, map { $data{$name}{$_} || '' } @codes;

Why does auto-vivification does not occur here? What makes perl decide to go the OR (||) route to map null string to join function?

Thank you again. I know I have a long way to go in learning perl and will look forward to your guidance here on perl monks.

Regards, Jaypal

Replies are listed 'Best First'.
Re^3: Print something when key does not exist
by AnomalousMonk (Archbishop) on Apr 06, 2014 at 04:43 UTC
    ... I never seen fat comma (=>) used in join. Is this because we wanted the $sep to be quoted and fat comma will do that for us?

    In this case, use of the fat comma is a personal notational convention.  $sep is already 'quoted'; that is to say, it is already a string, and there's nothing you could do to make it stringier. If it had been a bareword instead (and assuming strictures and warnings enabled), use of a fat comma would have caused the bareword to be treated as a string.

    c:\@Work\Perl\monks>perl -wMstrict -le "my $s = join foo => 1, 2, 3, 4; print qq{'$s'}; " '1foo2foo3foo4'

    In fact, any legal expression will be 'stringized' for use by join:

    c:\@Work\Perl\monks>perl -wMstrict -le "my $s = join 8, qw(foo bar baz); print qq{'$s'}; " 'foo8bar8baz'
Re^3: Print something when key does not exist
by kcott (Archbishop) on Apr 06, 2014 at 11:36 UTC
    "Hello Ken, I can't thank you enough for the time and effort spent on such detailed and fantastic analysis. This is your second answer to my two posts here on perl monks and I can say for sure that I have learnt so much from your answers than I could ever have by reading a book."

    You've shown a genuine desire to learn and have put thought into your questions: I'm more than happy to help. As I often say, "A better question gets better answers."

    "One follow up question, I never seen fat comma (=>) used in join. Is this because we wanted the $sep to be quoted and fat comma will do that for us?"

    As ++AnomalousMonk correctly identified, and went on to answer in more detail, this is a personal preference.

    There's a quite a few functions whose first argument describes how it should operate, with the remaining arguments indicating what it should operate on. (Some exmples, just off the top of my head and in no particular order, would include: join, sprintf and pack.) In these cases, I often use a fat comma to separate the "how-to-operate" and the "what-to-operate-on" arguments. I find it can improve readability in many cases but, where it doesn't, I don't use it. It's just a personal style preference: use whatever you feel most comfortable with.

    "Why does auto-vivification does not occur here?"

    Autovivification has changed as Perl has matured: it used to happen a lot more than it does in more recent versions. (The changes mostly seem to be for optimisation purposes but that's purely a guess on my part.) As I've been using Perl since Perl3, and don't always recall every change that has been made, I do find that I sometimes need to check whether autovivification is occurring in a particular context: the script I provided was a case in point and a simple "use Data::Dump; dd \%data;" at the end of the code confirmed what I thought was happening.

    $name is known to be a key of %data because it was returned by keys %data; therefore, $data{$name} doesn't need to be autovivified to check for $data{$name}{$_}. If there's no $data{$name}{$_} key, it doesn't need to be autovivified because, in the boolean context, it's known to be FALSE and that's all that needs to be known; it's not, for instance, being used as an lvalue or passed as an argument.

    If $name had come from another source and $data{$name} didn't exist, it would need to be autovivified; however, $data{$name}{$_} still wouldn't need to be autovivified for the reasons just given.

    Here's a quick test to clarify those points:

    $ perl -Mstrict -Mwarnings -MData::Dump -le ' my %x = (a => { B => 2 }); for my $key (qw{a b}) { print join "^" => map { $x{$key}{$_} || "undef" } qw{B C}; dd \%x; } ' 2^undef { a => { B => 2 } } undef^undef { a => { B => 2 }, b => {} }

    $x{b} was autovivified where it was needed. None of $x{a}{C}, $x{b}{B} or $x{b}{C} were autovivified because they weren't needed beyond the boolean context where just knowing that they didn't exist was sufficient.

    If I'm ever not 100% sure, I find a quick check is faster than trying to analyse all the code involved and can avoid potential late night debugging sessions.

    You'll find some more information on this in perldata and perlref.

    "What makes perl decide to go the OR (||) route to map null string to join function?"

    There are several things that are deemed to be FALSE in a boolean context. An undefined value is one of these. See "perlsyn: Truth and Falsehood" for more details.

    -- Ken

      ... I often use a fat comma to separate the "how-to-operate" and the "what-to-operate-on" arguments.

      My favorite personal "off-label" usage of  => is in an OO-code statement like
          return bless $objectref => $class;
      for what I imagine to be its self-documenting qualities: "bless object reference into class."

        I'd forgotten about that. Years ago I used to hand-roll OO classes almost on a daily basis and used the fat comma in bless $objectref => $class for exactly the same reason.

        There's a few others that have that similar "self-documenting qualities"; for instance, to send a signal to a process:

        kill SIGNAL => $pid

        -- Ken

      Thanks Ken for the kind words. That example you provided for auto-vivification was really helpful. Have a great rest of the weekend. :)