Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Hidden Secrets of PERL

by perl_lover (Chaplain)
on Oct 11, 2006 at 08:46 UTC ( [id://577561]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

C has lot of reference materials and Books to explore the hidden treasures. Does PERL has any books/Reference to explore its hidden treasures.
I am looking something like,
$a = 10; $b = 20; print $a +$b;
This code will not print 30 as there is ambiguity in the print statement. It treats $a as file handle and + before the $b as prefix operator and tries to print $b to $a.

Is there any place where these kind of hidden treasures are listed ?

-perl_lover-

Replies are listed 'Best First'.
Re: Hidden Secrets of PERL
by shmem (Chancellor) on Oct 11, 2006 at 09:56 UTC
    I'd call you example pitfall or trap for the unwary rather than a hidden treasure. It's normal behaviour, and no, there is no such book - there's the perl documentation. Perl just is like that, it's all about context.

    Oh, wait - if you seek odd things, unexpected behaviour and such, have a look at The Golf Book.

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Hidden Secrets of PERL
by zentara (Archbishop) on Oct 11, 2006 at 12:07 UTC
Re: Hidden Secrets of PERL
by jdporter (Paladin) on Oct 11, 2006 at 14:24 UTC

    perltrap

    (also appearing as "Common Goofs for Novices" in the Camel book.)


Re: Hidden Secrets of PERL
by blazar (Canon) on Oct 11, 2006 at 10:01 UTC
    C has lot of reference materials and Books to explore the hidden treasures. Does PERL has any books/Reference to explore its hidden treasures.

    It has excellent documentation in addition to many books.

    I am looking something like,
    $a = 10; $b = 20; print $a +$b;

    perldoc -f print.

    This code will not print 30 as there is ambiguity in the print statement. It treats $a as file handle and + before the $b as prefix operator and tries to print $b to $a.

    There is no ambiguity, although one has to admit that the case may be confusing. But it's perfectly well documented.

    Is there any place where these kind of hidden treasures are listed ?

    Again, in the docs, in which as a perl_lover you will also be delighted to discover that it's also explained why there's not such a thing as PERL: see perldoc -q difference between "perl" and "Perl".

      There is no ambiguity, although one has to admit that the case may be confusing. But it's perfectly well documented.
      Eh, no... there is ambiguity as the syntax of this piece of code is ambiguous for the grammar.

      Only, Perl has a well documented way to disambiguate this case.

      Other ambiguities include code block versus anonymous hash, and the opening slash for regexes for optional function arguments:

      map { $_ => length } @list # code block or hash?
      rand /2 /m # division or regex?

      Occasionally, in particular for the former example, Pelr makes an initial guess and guesses wrong, producing a syntax error further down in the parsing stream — too late to go back and try the other route. It requires a well known disambiguation trick to resolve the problem, early enough:

      +{ $_ => length } # hashref { ; $_ => length } # code block
        Only, Perl has a well documented way to disambiguate this case.

        If it does, it certainly doesn't say so in the documentation of print. This is the documentation of print (from 5.8.5):

               print FILEHANDLE LIST
               print LIST
               print   Prints a string or a list of strings.  Returns true if success-
                       ful.  FILEHANDLE may be a scalar variable name, in which case
                       the variable contains the name of or a reference to the file-
                       handle, thus introducing one level of indirection.  (NOTE: If
                       FILEHANDLE is a variable and the next token is a term, it may
                       be misinterpreted as an operator unless you interpose a "+" or
                       put parentheses around the arguments.)  If FILEHANDLE is omit-
                       ted, prints by default to standard output (or to the last
                       selected output channel--see "select").  If LIST is also omit-
                       ted, prints $_ to the currently selected output channel.  To
                       set the default output channel to something other than STDOUT
                       use the select operation.  The current value of $, (if any) is
                       printed between each LIST item.  The current value of "$\" (if
                       any) is printed after the entire LIST has been printed.
                       Because print takes a LIST, anything in the LIST is evaluated
                       in list context, and any subroutine that you call will have one
                       or more of its expressions evaluated in list context.  Also be
                       careful not to follow the print keyword with a left parenthesis
                       unless you want the corresponding right parenthesis to termi-
                       nate the arguments to the print--interpose a "+" or put paren-
                       theses around all the arguments.
        
                       Note that if you're storing FILEHANDLES in an array or other
                       expression, you will have to use a block returning its value
                       instead:
        
                           print { $files[$i] } "stuff\n";
                           print { $OK ? STDOUT : STDERR } "stuff\n";
        

        The only part that hints about ambiguaty is the part I boldfaced. But it doesn't explain at all why it parses the statement differently whether there's a space between the third and fourth token. Not that I expect most programmers to know what the phrase next token is a term means.

Re: Hidden Secrets of PERL
by fenLisesi (Priest) on Oct 11, 2006 at 11:39 UTC
    Not directly related to your question, $a and $b are not the best choices for variable names, as they are special.
Re: Hidden Secrets of PERL
by tilly (Archbishop) on Oct 11, 2006 at 22:42 UTC
    I would try unravelling stuff in the Obfuscation section.

    BTW congratulations. It has been a long time since something was pointed out to me about Perl that truly made me go, Ick! You succeeded.

    BTW trading oddities, why do the following two programs print different things?

    ####### ## A ## ####### use strict; my $foo; $foo = "outside"; for $foo (qw(a b c)) { print_foo(); } sub print_foo { print "$foo\n"; } __END__ ####### ## B ## ####### use strict; our $foo; $foo = "outside"; for $foo (qw(a b c)) { print_foo(); } sub print_foo { print "$foo\n"; } __END__

      If the variable that is going to hold each value in an loop already exists as a lexical one (first example), foreach creates a new lexical whose scope is the loop block. If it exists as a package global (second example), foreach localizes it, thus making its scope dynamic. That's why second example's print_foo sees the dynamic content.

      --
      David Serrano

        Indeed and this is documented in perlsyn under the heading "foreach loops":
        The foreach loop iterates over a normal list value and sets the variable VAR to be each element of the list in turn. If the variable is preceded with the keyword my, then it is lexically scoped, and is therefore visible only within the loop. Otherwise, the variable is implicitly local to the loop and regains its former value upon exiting the loop. If the variable was previously declared with my, it uses that variable instead of the global one, but it's still localized to the loop. This implicit localisation occurs only in a foreach loop.

        OTOH, it doesn't seem to be really localized, instead, it appears to be a totally different lexical.

      Allow me to toil in some scrivener's work. In the "Non-Lexical Loop Iterators" section of PBP, the oracle speaks:
      Always declare a for loop iterator variable with my.
      and goes on to explain that, if there happens to be a lexical variable with the same name as the loop variable declared before the loop, that lexical variable is not reused within the loop, but a brand new independent lexical variable is implicitly created to take effect within the scope of the loop alone. Quoting the discussion there:
      This behaviour is contrary to all reasonable expectation. Everywhere else in Perl, when you declare a lexical variable, it is visible throughout the remainder of its scope, unless another explicit my declaration hides it.
      Update: wfsp sent me a link to this related node.
        The reason is history. The ability to write:
        foreach my $variable (LIST) {...}
        was relatively recent (5.004 I think). Before one had to write
        my $variable; foreach $variable (LIST) {...}

        As usual, it's combining old Perl DWIM, new features and backwards compatability that leads to oddities like this. Luckely, for most people, it all just works, and old programs don't break.

Re: Hidden Secrets of PERL
by jbrugger (Parson) on Oct 12, 2006 at 05:33 UTC
    Not a real hidden secret, and mentioned on this site before: (however i use it, since it's save for my examle): the x operator.
    have a look at the following example:
    my $sql = join(",", @allsearchterms); my $sth = $dbh->prepare("select * from table where value in($sql)"); # You need to place qutes arount the sql-items, but you'll get the poi +nt here... $sth->execute();
    As you know, this isn't safe (sql Piggybacking)
    Now concider the next code example:
    my $qm = join ',', ('?') x @allsearchterms; my $sth = $dbh->prepare("select * from table where value in($qm)"); $sth->execute(@allsearchterms);
    As you see, a neat feature of Perl :)

    Update:
    code adjusted as suggested by Hue-Bond

    "We all agree on the necessity of compromise. We just can't agree on when it's necessary to compromise." - Larry Wall.
      My $qm = '?,'x scalar(@allsearchterms);

      The argument at the right of x is in scalar context, so no need to call scalar. Besides it, you can use join to get rid of the chop:

      my $qm = join ',', ('?') x @allsearchterms;

      --
      David Serrano

Re: Hidden Secrets of PERL
by Anonymous Monk on Oct 13, 2006 at 11:14 UTC
    @a=(1,2,3); foreach my $r (@a) { $r=2; } print @a;
    Have a fun ;-)

      What you are experiencing is that for(each) loops alias the iterator variable to each member of the list in turn. This can be written to, as this scriptlet demonstrates.

      From perldoc perlsyn:

      If any element of LIST is an lvalue, you can modify it by modifying VAR inside the loop. Conversely, if any element of LIST is NOT an lvalue, any attempt to modify that element will fail. In other words, the foreach loop index variable is an implicit alias for each item in the list that you're looping over.

      --

      Oh Lord, won’t you burn me a Knoppix CD ?
      My friends all rate Windows, I must disagree.
      Your powers of persuasion will set them all free,
      So oh Lord, won’t you burn me a Knoppix CD ?
      (Missquoting Janis Joplin)

A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

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

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

    No recent polls found