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

What's this line means in HTTP::headers?

by anaconda_wly (Scribe)
on Sep 05, 2013 at 02:33 UTC ( #1052471=perlquestion: print w/ replies, xml ) Need Help??
anaconda_wly has asked for the wisdom of the Perl Monks concerning the following question:

I'm reading HTTP::headers code. I understand what GET mean, when only one argument, @_ becomes empty and $op will choose GET. But I can't understand PUSH and SET logic before the 2nd "?". Before receiving any value, $seen{field_name} must be empty, so what does $seen{field_name}++ mean? What's difference of PUSH and SET?

Another question is if wantarray line. I read http://perldoc.perl.org/functions/wantarray.html but didn't understand."if the context of the currently executing subroutine or eval is looking for a list value". What "the context" refers here, @old returned by $self->_header?

sub header { my $self = shift; Carp::croak('Usage: $h->header($field, ...)') unless @_; my(@old); my %seen; while (@_) { my $field = shift; my $op = @_ ? ($seen{lc($field)}++ ? 'PUSH' : 'SET') : 'GET'; @old = $self->_header($field, shift, $op); } return @old if wantarray; return $old[0] if @old <= 1; join(", ", @old); }

I delete the line about "++" to state more clear about my question.

Comment on What's this line means in HTTP::headers?
Download Code
Re: What's this line means in HTTP::headers?
by Anonymous Monk on Sep 05, 2013 at 02:42 UTC
Re: What's this line means in HTTP::headers? ("the context")
by Anonymous Monk on Sep 05, 2013 at 02:49 UTC
      Yes, I know Auto-increment sign but just didn't understand the outcome here.

      Also I know the context meaning in some cases saying

      my $var = @array

      But here in specific case:

      return @old if wantarray;
      Does that mean if wantarray is always true? since @old is always an array?
        No. wantarray has nothing to do with @old, it has to do with how sub header is called, in what context.
Re: What's this line means in HTTP::headers?
by kcott (Abbot) on Sep 05, 2013 at 03:50 UTC

    G'day anaconda_wly,

    Here's a breakdown of what's happening with:

    my $op = @_ ? ($seen{lc($field)}++ ? 'PUSH' : 'SET') : 'GET';

    You've got a nested ternary operator here. Firstly, looking at the outer ternary. You've said you understand that when @_ is empty (i.e. FALSE), $op is assigned 'GET'. So, if @_ is not empty (i.e. TRUE), $op is assigned whatever ($seen{lc($field)}++ ? 'PUSH' : 'SET') evaluates to.

    "($seen{lc($field)}++ ? 'PUSH' : 'SET')" is the nested ternary. If ($seen{lc($field)}++ is TRUE, 'PUSH' will be assigned to $op; if it's FALSE, then 'SET' will be assigned to $op.

    "$seen{lc($field)}++" uses the postfix increment operator. This means that the value is returned first; afterwards the increment is performed. If the '++' was at the front (the prefix increment operator), the increment would be performed first and the incremented value would be returned. A simple code example might explain this better:

    $ perl -Mstrict -Mwarnings -le ' my $x = 1; print $x++; print $x; my $y = 2; print ++$y; ' 1 2 3

    $x starts as 1; $x++ evaluates to 1 for its print statement; afterwards, it's incremented to 2 as print $x shows. $y starts as 2; ++$y evaluates to 3 for its print statement, i.e. the increment is done first.

    Back to "$seen{lc($field)}++". If %seen doesn't have a key lc($field), then $seen{lc($field)} will evaluate to FALSE (i.e. $op = 'PUSH'); after that evaluation, $seen{lc($field)} is incremented with the key being created (that's called autovivification) and the value being set at 1 (FALSE in numeric context is zero; 0 + 1 = 1). If %seen does have a key lc($field), its value will be at least 1 and $seen{lc($field)} will evaluate to TRUE (i.e. $op = 'SET'); $seen{lc($field)} will then be incremented again.

    Using a hash called %seen (or similar name) and autovivifying keys (with a postfix increment) as they are seen is a common idiom. It would be worth your while studying this closely and ensuring you fully understand everything that's going on here: it's something you're likely to see often.

    For wantarray, the context is the calling context; it's got nothing to do with the context inside the executing subroutine. The following may suffice to explain this:

    my @return_values = function(@args); # wantarray TRUE my $return_value = function(@args); # wantarray FALSE

    -- Ken

      Thank you Ken. For wantarray, it's exactly answer what I want. I also tried a test.pl verify it. I understand PUSH and SET after reading your comments. My another question is about the reason of using the ++. If the 0(false) is added to 1, what's the incrementing for? It's not like an iterator's or a pointer's moving we normally see. The increasing didn't change anything seemingly.

      For "++" sign in Perl, I only use it in some simple cases and seldom embedded it into a complicated expression. In some language, "++"'s action is dependent on the compiler's implementation and I should know the language very well or may easily make error. When I saw "$seen{lc($field)}++", I'm thinking which operator wll take the highest priority to interpreter, "($seen{lc($field)})++" or "$seen({lc($field)}++)". I decided to find some artical about Perl Ops priority to read first.

        "My another question is about the reason of using the ++. If the 0(false) is added to 1, what's the incrementing for? It's not like an iterator's or a pointer's moving we normally see. The increasing didn't change anything seemingly."

        I don't understand what point you're making here. Take a look at these two scripts: the first with ++, the second without.

        $ perl -Mstrict -Mwarnings -le ' my @fields = qw{a a b c b a}; my %seen; for my $field (@fields) { print $field, $seen{$field}++ ? "PUSH" : "SET"; } ' aSET aPUSH bSET cSET bPUSH aPUSH
        $ perl -Mstrict -Mwarnings -le ' my @fields = qw{a a b c b a}; my %seen; for my $field (@fields) { print $field, $seen{$field} ? "PUSH" : "SET"; } ' aSET aSET bSET cSET bSET aSET

        That may clarify whatever is causing confusion or misunderstanding. If not, please supply a similarly short piece of code to explain your point.

        "... I decided to find some artical about Perl Ops priority to read first."

        Take a look at "perlop - Perl operators and precedence". There's a table of precedence and associativity at the start of the documentation. While you're there, you might as well also look at these sections further down the page: "Auto-increment and Auto-decrement" for "++" and Conditional Operator for "?:".

        -- Ken

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1052471]
Approved by kcott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (7)
As of 2014-04-24 09:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (565 votes), past polls