http://www.perlmonks.org?node_id=241370


in reply to GetOpt::Long usage style

Purely from a code clarity and locality point, this is better. It is however a bit difficult to figure out why it works (anything but blindingly obvious, at least to me). Let me try to figure it out for my own good - correct me if I'm wrong:
my $verbose='';
That's easy - $verbose becomes an empty scalar. This is also easy:
(my $verbose='');
This is an empty list (or better, a list containing that particular piece of emptiness referenced by $verbose.

And here comes the hairy part:

\(my $verbose='');
This is a reference to that particular piece of emptiness pointed to by $verbose, hence in a sense (though strictly speaking not) a reference to $verbose. We're basically pointing to the same scalar thingy as $verbose is pointing to, so when GetOpt::Long uses this reference to stash the option value, we can use $verbose to get at that value. Correct?

That is a very neat trick, sir! Despite the minor headache in figuring it out (for me anyway), I think I shall be using it from now on. Perhaps you need to figure out a catchy name for it :) ?

CU
Robartes-

Replies are listed 'Best First'.
Re: Re: GetOpt::Long usage style
by demerphq (Chancellor) on Mar 08, 2003 at 12:32 UTC

    \(my $verbose='');

    my returns what has been declared. (Although the behaviour of it as a function is a little interesting, I dont think it can be prototyped, and I can't find complete documentation for it off hand.) The parenthesis required because the precedence of the assignment operator causes

    GetOptions(x=>my $x=1,y=>my $y);

    to be parsed something like

    GetOptions('x',(my $x=1,y=>my $y));

    which is a syntax error. They aren't required when the variable isn't initialized as part of the my. Also I personally think that they add visual calrity when the reference to the variable is taken. Since the my returns the variable declared (as an lvalue) we can take a reference to it with \. The reference operator \ can technically go inside the parens or outside in this case as

    \($x,$y,$z)

    is shorthand for

    (\$x,\$y,\$z)

    Hope that clarifys things. ;-) Er, and yes. You analysed it correctly. :-)

    A couple of related tricks are:

    my $txt="Foo bar"; (my $clean=$txt)=~s/oo/u/g; open my $fh,"File" or die "File $!"; if (my ($x,$y,$z)=/A(..)(..)(..)Z/) { }

    ---
    demerphq


      I know this is ancient, but since it's high on the Google hit list, I wanted to mention one thing...

      This very cool trick does not work for @arrays. :-(

      This:

      use Getopt::Long; GetOptions( 'single=s' => \(my $single = ''), 'multi=s' => \(my @multi = ()), );
      does *NOT* DWIM. According to "perlref":
      As a special case, "\(@foo)" returns a list of references to the contents of @foo, not a reference to @foo itself.
      I tried all kinds of permutations, and the best I could come up with was:
      use Getopt::Long; GetOptions( 'single=s' => \(my $single = ''), 'multi=s' => do { use vars '@multi'; \@multi }, );
      which, isn't quite as clean, IMHO.

      (It *DOES*, however, keep the variable declarations and command-line options on the same line, at least, so you don't have to make changes in multiple places when adding new options. *shrug*)

        use Getopt::Long; GetOptions( 'single=s' => \(my $single = ''), 'multi=s' => \my @multi, );

        If you want to provide a non-empty default value, one way is:

        use Getopt::Long; GetOptions( 'single=s' => \(my $single = ''), 'multi=s' => grep { @$_ = ('a','b') } \my @multi, );

        - tye        

        Besides what tye said in Re^4: GetOpt::Long usage style (\my @a), you can just use an arrayref instead. Obviously the reference operator \ required for scalars can be omitted.

        'multi=s' => (my $multi = [1..3]),

        Same for a hash/hashref. Admittedly it is not quite the same as what one would expect from

        'multi=s' => (\my @multi = (1..3)),

        Which throws an error, which I think is arguably an error in Perl.

        BTW, sorry it took me so long to reply, and thanks for adding your point.

        ---
        $world=~s/war/peace/g

Re: GetOpt::Long usage style
by Abigail-II (Bishop) on Mar 08, 2003 at 23:00 UTC
    This is also easy:
    (my $verbose='');
    This is an empty list (or better, a list containing that particular piece of emptiness referenced by $verbose.

    You might call it easy, but it's wrong. Twice. First of all, parenthesis do NOT make lists. Context makes lists. Parenthesis are used for precedence.
    Furthermore, if the context would demand a list (which in this case it does), it's not an empty list. How could it be? There's a scalar inside it. It's a one element list.

    Abigail

      Goes to show again that I feel perfectly comfortable with my foot in my mouth. Thanks for the heads up, demerpq, zby and Abigail-II!

      CU
      Robartes-

Re: Re: GetOpt::Long usage style
by zby (Vicar) on Mar 08, 2003 at 17:04 UTC
    I have not a Perl reference at hand now but I think that \($something) is the same as (\$something). That is the \ operator for a list returns a list of references not a reference to a list.

    UPDATEOK - writing about no having a reference on a web site was a bit lame.