Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Need Help in Understanding Some Code - Map and Scalar Questions

by Dru (Hermit)
on Oct 30, 2010 at 18:27 UTC ( [id://868491]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks,

I am trying to enlighten myself by reading as much code on here as possible and figuring out the parts that I do not understand. I came across this post Networking Perl today and Your Mother's reply had the following code
use warnings; use strict; use JSON; use Plack::Request; use Proc::ProcessTable; sub { my $req = Plack::Request->new(+shift); my %pids = map { $_ => 1 } $req->path =~ /(\d+)/g; my $procs = Proc::ProcessTable->new; my $json = JSON->new; my %status; for my $proc ( @{ $procs->table } ) { next if scalar(%pids) and not $pids{$proc->pid}; for my $field ( $procs->fields ) { $status{$proc->pid}{$field} = $proc->$field; } } return [ 200, [ "Content-Type" => "application/json" ], [ $json->pretty->encode(\%status) ] ]; };
There are two items in this that are giving me trouble. First this map, I don't quite understand what it is doing (it seems no matter how much I read about map I still can't quite grasp it):
my %pids = map { $_ => 1 } $req->path =~ /(\d+)/g;
Is it saying "For each item found in $req->path that is a number save it as a hash key of %pids?"

The other thing that confuses me is this
next if scalar(%pids) and not $pids{$proc->pid};
I know "scalar(%pids)" will force the hash %pids to be interpreted in scalar context, but to be honest with you I do not know exactly what this will do to the hash. I tried testing this on my own with the following code:
my %hash = ( fred => flintstone, wilma => flintstone, barney => ruble, ); print scalar(%hash) . "\n";
But this prints out "3/8" so I'm really confused.

Thank you for helping me on my journey.

Thanks,
Dru

Perl, the Leatherman of Programming languages. - qazwart

Replies are listed 'Best First'.
Re: Need Help in Understanding Some Code - Map and Scalar Questions
by ikegami (Patriarch) on Oct 30, 2010 at 18:53 UTC

    Is it saying "For each item found in $req->path that is a number save it as a hash key of %pids?"

    Yes. The argument ($req->path =~ /(\d+)/g;) is evaluated first, and it returns a list of numbers. map then pairs each number of the list (say 1,2,3) with "1"s (1=>1,2=>1,3=>1). That's assigned to the hash.

    but to be honest with you I do not know exactly what this will do to the hash.

    A hash in scalar context evaluates to something false if the hash is empty, or to some statistics about the hash if it's not.

    (Starting with 5.12.? or 5.14.0, this is optimised to not create the statistics string if a boolean value is expected, returning a simple true value instead.)

    The other thing that confuses me is next if scalar(%pids) and not $pids{$proc->pid};

    Do the the next iteration of the loop if the hash isn't empty and the hash doesn't contain the $proc's pid.

Re: Need Help in Understanding Some Code - Map and Scalar Questions
by AnomalousMonk (Archbishop) on Oct 30, 2010 at 21:42 UTC

    Maybe I'm having a senior moment here, but I can't see how the statement in the OPed code
        sub { ... };
        # wander away...
    can possibly do anything at all.

    One could define and subsequently invoke a subroutine
        sub func { ... }
        # some other stuff...
        func();
    or define and save a reference to a subroutine and subsequently invoke it
        my $coderef = sub { ... };
        # some other stuff...
        $coderef->();
    or define a reference to a subroutine and immediately invoke it
        sub { ... }->();
    but I don't understand the definition of the OPed code, which just seems to define a subroutine reference and then immediately throw it away.

    Am I missing something?

      Maybe I'm having a senior moment here…

      Hee-hee. The code was contained in a script called proc.psgi so it's final value is an anonymous sub. Somewhat like a module must return true, a PSGI app must return its code ref. See http://plackperl.org/. Plack is all kinds of wonderful.

        ... a PSGI app must return its code ref.

        Ah, the mist begins to clear.

Re: Need Help in Understanding Some Code - Map and Scalar Questions
by Your Mother (Archbishop) on Oct 30, 2010 at 19:41 UTC

    Worth mentioning: this isn't exactly the kind of code I'd write for anything but fun. It's a bit too terse/idiomatic. It is nice to be able to do a lot in a small space, especially for this kind of prototype, but for code you expect to live awhile or you want to share or test easily it's much better to abstract that kind of stuff (argument parsing and dispatch) into another space so it can be semantic in usage and easy to follow in the pertinent source code.

    So, it's not surprising this was confusing. The idioms ikegami explained are pretty common and worth knowing and understanding regardless. Also of interest: site:perlmonks.org Schwartzian Transform.

Re: Need Help in Understanding Some Code - Map and Scalar Questions
by MishaMoose (Scribe) on Oct 30, 2010 at 19:11 UTC

    I seem to recall having read recently that the 3/8 returned for this scalr'd hash means 3 or the 8 allocated buckets for this hash are used.

    I also think I recall that you can pre allocate the number of buckets by something like

    %hash = 100;

    which I thought was pretty interesting. But sadly I don't remember the reference and am away for my books. I hope one of the more enlightened will correct any error.

    Misha/Michael - Russian student, grognard, bemused observer of humanity and self professed programmer with delusions of relevance
Re: Need Help in Understanding Some Code - Map and Scalar Questions
by TomDLux (Vicar) on Oct 31, 2010 at 18:03 UTC

    What next if scalar(%pids) and not $pids{$proc->pid}; is saying is: Ignore any pids in the process table which are not in our hash of pids mentioned in the Plack request path; don't process the rest of the loop for those, just go on to the next one. But actually, if the Plack hash is empty, don't even bother checking for whether the pid is present, since it won't be.

    Mind you, if the hash is empty, none of the pids will be present, so I would short circuit the whole routine and not test any of the pids. But it's easy to think of that now, when I have to explain things, I'm not guaranteeing i would think of it in that situation.

    You tried a hash with values in it, now try an empty hash ... you'll get back zero, which is false in boolean context.

    As Occam said: Entia non sunt multiplicanda praeter necessitatem.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2024-04-23 08:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found