Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Your favourite gory detail...

by Ido (Hermit)
on Jun 20, 2004 at 22:59 UTC ( [id://368339]=perlmeditation: print w/replies, xml ) Need Help??

Perl has so many weird behaviours (or behaviours which appear to be weird before you understand them...), exceptions and details.
When I think of "Perl's tiny details", the first thing that pops in my mind, ever since I've read about it, is the difference between \(@array,@brray) and \((@array),@brray). (And I have no idea why;)

So..What do you think of?What's your favourite "detail"?


P.S: Trying to Deparse the two, I get the same output...Seems like a bug to me... Or am I wrong?

Replies are listed 'Best First'.
Re: Your favourite gory detail...
by Zaxo (Archbishop) on Jun 21, 2004 at 05:33 UTC

    My favorite is a very general feature - the light-hearted way perl has with context. It is an annoyance to lovers of formalism that every perl builtin and function is free to return whatever it likes for the context it finds itself in. That is the essence of perl dwimmerie.

    After you master the difference between list and scalar context, you get to enjoy string and numeric contexts for your values. You can savor the numification and stringification of undef.

    Not only that, you get wantarray and use overload for '""', '0+' and 'bool', so you can play the game yourself!

    Delicious!

    After Compline,
    Zaxo

      Delicious!

      Agreed 100%. And just a little bit of extra effort in tailoring your subs to behave intelligently pays off in terms of usabily in a huge way.


      ---
      demerphq

        First they ignore you, then they laugh at you, then they fight you, then you win.
        -- Gandhi


Re: Your favourite gory detail...
by QM (Parson) on Jun 21, 2004 at 01:51 UTC
    Not really weird, but I sometimes get caught being too fancy. I try to do a s///, and expect it to return the matches as a list. Sometimes I write this:
    if ( ( $a, $b, $c ) = $current_text =~ s/$some_regex// ) { # do something useful next READ_MORE_DATA }
    in a parserish way. Then I have that forehead-slapping moment, and change it to this:
    if ( $current_text =~ s/$some_regex// ) { ( $a, $b, $c ) = ( $1, $2, $3 ); # do something useful next READ_MORE_DATA }

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

Re: Your favourite gory detail...
by BrowserUk (Patriarch) on Jun 20, 2004 at 23:20 UTC

    With regard to the "difference" between  \(@array, @brray) and \((@array), @brray)--there is none.

    In both cases, the contents of both arrays get flattened into a single list. The backslash is then applied to each element of that list. No amount of extra parens will change the outcome, which is a list of references to the elements of boths arrays.

    Update: My (least) favorite gory detail is the limitation of using prototypes to create your own map-like subs that I first encountered in Problem emulating built-ins like map and grep. and still get bitten by from time to time.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
      Er.. did you try it?
      use Data::Dumper; @array = (1,2,3); @brray = (4,5,6); print Dumper [ \(@array,@brray) ]; print Dumper [ \((@array),@brray) ]; __END__ $VAR1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; $VAR1 = [ \1, \2, \3, [ 4, 5, 6 ] ];
      This is perl, v5.8.4 built for i386-linux-thread-multi

      Update: oops, this should be a follow-up to BrowserUk's reply...

      blokhead

      Yes, there is a difference.

      \() is like a factored out reference operator before every thing inside the parenthesis, so \($foo, @bar, %baz, &frah) is (\$foo, \@bar, \%baz, \&frah), except if there's only one aggregate data type inside it. In that case it gets flattened and the backslash is then applied to each element of that list, as you say. This means that

      \((@foo), @bar)
      becomes
      (\(@foo), \@bar)
      which becomes
      (\($foo[0], $foo[1], ..., $foo[$#foo]), \@bar)
      and finally
      ((\$foo[0], \$foo[1], ..., \$foo[$#foo]), \@bar)

      Another example:

      \((@foo, @bar), @baz) (\(@foo, @bar), \@baz) ((\@foo, \@bar)), \@baz)

      Update: I just realized that my second example is rather useless as the end result is the same as if there was no inner parenthesis. But the intermediate step perhaps still has a pedagogical value.

      (I don't know if this recursive behaviour is how it's actually performed under the hood, but it works this way none the less.)

      ihb

      That's why I said it was WEIRD!;)

      Update: Gha..That too was meant to follow BrowserUk's..
Re: Your favourite gory detail...
by zentara (Archbishop) on Jun 21, 2004 at 13:21 UTC
    Mine's alot simpler: The requirement that "required scripts" and modules always have a "1;" at the end, so they return a true value.

    I'm not really a human, but I play one on earth. flash japh
      It doesn't have to be 1, it just has to be true. You could end your modules with 'false'; or 'the end'; if you want, as thosee strings evaluate to boolean true.
        Oooh, that's even "gorier". :-)

        I'm not really a human, but I play one on earth. flash japh
Re: Your favourite gory detail...
by Abigail-II (Bishop) on Jun 22, 2004 at 10:46 UTC
    My favourite detail must be the way -p and -n are handled. My least favourite detail is the significant whitespace in perl6:
    print sqrt (9) + 7; # prints 4. print sqrt(9) + 7; # prints 10.

    Abigail

Re: Your favourite gory detail...
by ihb (Deacon) on Jun 21, 2004 at 19:26 UTC

    This isn't exactly a favourite... The fact that there's a difference between ref and ref() is... well, it simply scares me. :-) It's almost like your example, a seemlingly innocent parethesis makes a huge difference, except the behaviour in your example makes sense and is consistent.

    An eof without an argument uses the last file read. Using eof() with empty parentheses is very different. It refers to the pseudo file formed from the files listed on the command line and accessed via the <> operator.

    So far it doesn't seem that evil. But wait, it goes on...

    Since <> isn't explicitly opened, as a normal filehandle is, an eof() before <> has been used will cause @ARGV to be examined to determine if input is available. Similarly, an eof() after <> has returned end-of-file will assume you are processing another @ARGV list, and if you haven't set @ARGV, will read input from STDIN;

    That's just too much magic for one parenthesis!

    ihb

      It does even more if you are using the -i flag.

      Update: to be more explicit, under -i, a simple eof() will (if needed) pull the next file(s) off of @ARGV, renaming and creating a new file for each until it gets to a non-empty one, and then selects that one as the default output file:

      $ rm foo{.bak,};echo bar>foo;perl -i.bak -we'sub show { print STDOUT " +files: ", join(",", glob("*")), "\nselected: $_\n" and select $_ for select *{" +TEMP"} } show; print STDOUT eof() ? "eof\n" : "not eof\n"; show' foo files: foo selected: main::STDOUT not eof files: foo,foo.bak selected: main::ARGVOUT
      The fact that there's a difference between ref and ref() is... well, it simply scares me. :-)

      Like what?

Re: Your favourite gory detail...
by japhy (Canon) on Jun 27, 2004 at 03:46 UTC
    This is one of my unfavorite details. An lvalue-d sub doesn't work quite right with a regex:
    { my $s; sub str :lvalue { $s } } str = "japhy"; pos(str) = 2; print pos(str); # prints 2! str =~ /\G(.)/ and print $1; # prints 'j', not 'p' print pos(str); # prints 2!
    Maybe I should perlbug this...
    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;
Re: Your favourite gory detail...
by tilly (Archbishop) on Jun 24, 2004 at 22:51 UTC
    That pos($foo) = pos($foo); is not a no-op.
      Took me about an hour to find code that has different output with and without that line... But it was fun;), so I won't spoil...

      $foo='hello'; for(1..5){ $foo=~/(?=(.))/g; pos($foo)=pos($foo); print $1 }

      "The additional state of being matched with zero-length is associated with the matched string, and is reset by each assignment to pos()."

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2024-03-19 02:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found