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

I am scratching my head a little...

Why is it that in my code the following, throws global symbol errors ...

my $META_HIDDEN = 1; sub META_HIDDEN : lvalue { $META_HIDDEN } my $META_EXT = 'meta'; sub META_EXT : lvalue { $META_EXT } my $to = $self->abs_loc . ( META_HIDDEN ? "/.$newname." : "/$newname." ) . META_EXT;

But if I change to the following ...everything is fine!

my $META_HIDDEN = 1; sub META_HIDDEN : lvalue { $META_HIDDEN } my $META_EXT = 'meta'; sub META_EXT : lvalue { $META_EXT } my $to; if (META_HIDDEN){ $to = $self->abs_loc . "/.$newname.". META_EXT; } else { $to = $self->abs_loc . "/$newname.". META_EXT; }

Am I missing something really dumb?

Replies are listed 'Best First'.
Re: funky error using lvalue subs in ternary assignment?
by ikegami (Patriarch) on Mar 27, 2007 at 19:43 UTC

    It has nothing to do with lvalue functions. The same problem occurs if it's not an lvalue function.

    Perl thinks you are using the ?...? operator (Look under "Quote and Quote-like Operators"). Omitting parens is dangerous.

    Change
    ( META_HIDDEN ? "/.$newname." : "/$newname." )
    to
    ( META_HIDDEN() ? "/.$newname." : "/$newname." )
    or to
    ( (META_HIDDEN) ? "/.$newname." : "/$newname." )

Re: funky error using lvalue subs in ternary assignment? (())
by tye (Sage) on Mar 27, 2007 at 19:51 UTC

    I only get global variable errors because $self wasn't declared. When I fix that, I get what I expected: the ? is interpreted as the start of the infrequently used form of m//.

    Write META_HIDDEN() not META_HIDDEN.

    - tye        

Re: funky error using lvalue subs in ternary assignment?
by Zaxo (Archbishop) on Mar 28, 2007 at 05:34 UTC

    Another way to make your original code work is to include an empty prototype in the sub definitions. That makes perl take the barewords as functions without argument while compiling. I imagine that is a side effect of constant folding.

    my $META_HIDDEN = 1; sub META_HIDDEN () : lvalue { $META_HIDDEN } my $META_EXT = 'meta'; sub META_EXT () : lvalue { $META_EXT } my $to = $self->abs_loc . ( META_HIDDEN ? "/.$newname." : "/$newname." ) . META_EXT;

    After Compline,
    Zaxo

Re: funky error using lvalue subs in ternary assignment?
by ferreira (Chaplain) on Mar 27, 2007 at 20:03 UTC

    Update: forget it, I said nonsenses.

    To add to ikegami's comment, it seems that in many places, you need explicit () to use lvalue functions. And this is how it is used in the examples given in perlsub (Lvalue subroutines). In simple pieces like if (META_HIDDEN) or META_EXT;, they don't look very ambiguous. So that Perl does the right thing. But things like META ? a : b, where META is lvalue, give a bad time to the interpreter. See:

    $ perl -MO=Deparse -e 'sub META : lvalue { $a } META ? a : b ' Search pattern not terminated or ternary operator parsed as search pat +tern at -e line 1. sub META : lvalue { $a; }

    There in the docs, there's a warning about the experimental status of lvalue subroutines and how their drawbacks (like violating encapsulation) can made them not such a good idea.