Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??

NAME

subtlety - the subtle things about perl


QUIRKS

The following is a list of some of the things that have surprised me about Perl.


+shift;

This feature of Perl represented the first (and only?) time Keith <<A HREF="mailto:keith@lbox.org>">keith@lbox.org> stumped me w/ a Perl question. The most common use of shift is to take parameters off of @_ and put them into scalars.

sub foo { my $self = shift; my $hash_ref = shift;

# and so on... }

What if you wanted to have a local copy of the hash instead of working directly with the hash reference? You can't say:

    my %hash = %{ shift };

The reason for this is because perl doesn't know whether you mean %shift or whether you're trying to execute the built-in shift. To remedy this (w/o using more variables) you can say:

    my %hash = %{ +shift };

Now it works. Why?! The unary + operator is a hint to the perl interpreter that it's not a variable name (because variable names cannot start w/ a ``+''). shift can still be a built-in at this point so that's what the perl interpreter treats it as. By the time %{ } comes around, shift has returned a a hash reference that can be cast into a hash. The + binds tighter than the %{ }.

Another (less obfuscated) way of doing this is:

    my %hash = %{ shift() };

The () binds tighter than the %{ }, so this achieves the same thing.


Perl built-ins are not subroutines.

I wrote a script called lchtml that would lowercase HTML tags and attributes while leaving the rest of the content alone. I thought it would be nice to be able to uppercase these things as well, so my first thought was to make it so that the routines that did the text transformation could take a subroutine reference as a parameter. When I wanted to lowercase, I'd give it \&lc and when I wanted to uppercase, I'd give it \&uc.

It didn't work. The built-in functions lc and uc (or any other built-in for that matter) aren't really subroutines. You can't take their reference. This was the first time I felt deep disappointment in Perl. I accept the fact that Perl is not 'orthogonal', but this was a little too far.

My work-around was to create wrapper subroutines that looked like:

sub my_lc { lc +shift; } sub my_uc { uc +shift; }

and pass around references to these wrapper subroutines. It made me feel dirty.


Sub-expression matches in array context.

Note that the following printf is receiving its parameters from the sub-expressions in the regular expression.

    printf("#%02x%02x%02x %s\n", /(\d+)\s+(\d+)\s+(\d+)\s+(.*)/);

In array context, the sub-expressions ($1, $2, $3, ...) will be returned as a list.


The difference between <STDIN> and <>.

One would think that <> would just read from STDIN, but what if there's nothing to be read from STDIN? Did you know <> will try to iterate over @ARGV, instead? It'll try to open each thing in @ARGV as if it were a file, and then try to read from that file. Make a script that does:

#!/usr/bin/perl while (<>) { print "$_\n"; }

and then invoke it like:

$ ./script a b c Can't open a: No such file or directory Can't open b: No such file or directory Can't open c: No such file or directory

If any of those files (a, b, or c) were to exist, it would have printed them to STDOUT. If the script had said <STDIN>, @ARGV would have been left alone.


\ is a list operator

Usually, one uses \ in scalar context to get the reference of one thing, but you can also use it in array context.

    @ref = \($a, $b, $c);

will take the reference of $a, $b, and $c and put them in @ref. If you ever need to take the reference of a bunch of things at once, this might be the idiom to use.


Mixing long and short options with Getopt::Long

This is documented under the ``Aliases and Abbreviations'' section of Getopt::Long's man page, but if you're not reading carefully, you will miss it. You can specify alternatives to an option by separating them with the pipe character |. Suppose you wanted people to be able to specify a size on the command line. If you want them to have the option to use either ``--size'' or ``-s''. To do this you can say:

my %opt; GetOptions(\%opt, "size|s=i");


SEE ALSO

Perl Monks -- you pick up on a lot of weird things perl can do.

http://perlmonks.org


In reply to Subtle Quirks by beppu

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • Outside of code tags, you may need to use entities for some characters:
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others drinking their drinks and smoking their pipes about the Monastery: (7)
    As of 2014-08-21 03:03 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      The best computer themed movie is:











      Results (127 votes), past polls