Why does this work?

E

Eric Schwartz

Why does this pass a perl -c? Shouldn't the call to catch() fail on
an unquoted bareword? It's kinda cool in that it lets me do things
like that, but I'm a bit nervous that it might magically go away some
day.

#!/usr/bin/perl
use warnings;
use strict;

sub catch
{
return 1;
}

catch( -force, "this shouldn't work, should it?");

-=Eric
 
A

A. Sinan Unur

Why does this pass a perl -c? Shouldn't the call to catch() fail on
an unquoted bareword? It's kinda cool in that it lets me do things
like that, but I'm a bit nervous that it might magically go away some
day.

#!/usr/bin/perl
use warnings;
use strict;

sub catch
{
return 1;
}

catch( -force, "this shouldn't work, should it?");

Does this help?

#!/usr/bin/perl
use warnings;
use strict;

use Data::Dumper;

my @array = -force;
print Dumper \@array;

my %hash = ( -force, 1 );
print Dumper \%hash;
__END__


C:\Dload> t4.pl
$VAR1 = [
'-force'
];
$VAR1 = {
'-force' => 1
};

I have been pulling my hair out trying to remember where this behavior is
described, but I remember seeing a note somewhere regarding the
autoquoting of words that start with a dash.
 
G

Gunnar Hjalmarsson

Eric said:
Why does this pass a perl -c? Shouldn't the call to catch() fail on
an unquoted bareword? It's kinda cool in that it lets me do things
like that, but I'm a bit nervous that it might magically go away some
day.

#!/usr/bin/perl
use warnings;
use strict;

sub catch
{
return 1;
}

catch( -force, "this shouldn't work, should it?");

From "perldoc perlop":

"Unary ``-'' performs arithmetic negation if the operand is numeric. If
the operand is an identifier, a string consisting of a minus sign
concatenated with the identifier is returned. Otherwise, if the string
starts with a plus or minus, a string starting with the opposite sign is
returned. One effect of these rules is that -bareword is equivalent to
"-bareword"."
 
B

Brian McCauley

A. Sinan Unur said:
I have been pulling my hair out trying to remember where this behavior is
described, but I remember seeing a note somewhere regarding the
autoquoting of words that start with a dash.

They are not fully autoquoted

$ perl -e"print -shift, 666" foo
-foo666
$ perl -e"print -shift => 666" foo
-shift666

I would consider the behaviour described in this thread to be a
(non-serious) bug in Perl and I would consider any script reliant on
this behaviour to be expoiting a bug in Perl and hense itself broken.
 
M

Michele Dondi

$ perl -e"print -shift, 666" foo
-foo666
$ perl -e"print -shift => 666" foo
-shift666

I would consider the behaviour described in this thread to be a
(non-serious) bug in Perl and I would consider any script reliant on
this behaviour to be expoiting a bug in Perl and hense itself broken.

It's not clear to me if you still consider it to be a bug also as per
the second example you gave. Because in that case you probably know
that that Tk thoroughly relies on it...


Michele
 
J

Joe Smith

The => operator is documented as quoting the previous bareword,
and if that bareword is preceded by a hyphen, it too is quoted.
They are not fully autoquoted

$ perl -e"print -shift, 666" foo
-foo666
$ perl -e"print -shift => 666" foo
-shift666

I would consider the behaviour described in this thread to be a
(non-serious) bug in Perl

It is not a bug. It is a feature that was deliberately added to
the language and is documented.
-Joe
 
B

Bart Lateur

Joe said:
Brian McCauley wrote:
It is not a bug. It is a feature that was deliberately added to
the language and is documented.

You're missing the point.

use strict; print -force

prints:

-force

both in 5.6.1 as in 5.8.3. For some reason, strict seems to be too
relaxed here. Maybe that is by design too, to allow for emulation of
named parameters more easily.
 
B

Brian McCauley

Abigail said:
Bart Lateur ([email protected]) wrote on MMMMCXXXVIII September
MCMXCIII in <URL:-: Joe Smith wrote:
-:
-: >Brian McCauley wrote:
-:
-: >> I would consider the behaviour described in this thread to be a
-: >> (non-serious) bug in Perl
-:
-: >It is not a bug. It is a feature that was deliberately added to
-: >the language and is documented.
-:
-: You're missing the point.
-:
-: use strict; print -force
-:
-: prints:
-:
-: -force
-:
-: both in 5.6.1 as in 5.8.3. For some reason, strict seems to be too
-: relaxed here. Maybe that is by design too, to allow for emulation of
-: named parameters more easily.


By design, and documented. From perlop/Symbolic Unary Operators:

Unary "-" performs arithmetic negation if the operand is
numeric. If the operand is an identifier, a string con­
sisting of a minus sign concatenated with the identifier
is returned. Otherwise, if the string starts with a plus
or minus, a string starting with the opposite sign is
returned. One effect of these rules is that -bareword is
equivalent to "-bareword".

Hmmm... I suspect "by design" is a little too strong. But I'll grant
you that the fact that -bareword is allowed under strict is implied by
the statement "If the operand is an identifier..." so it's a feature not
a bug.

If you want to use the fact that the current behaviour matches the
documented behaviour as justification that something's not a bug then
perhaps I should point out that the actual behaviour does not match the
above documentation fragment!

sub foo { 'bar' };
print -foo;

The above prints '-bar' not '-foo' and also emits a warning even without
"use warnings" in effect.
 
B

Bart Lateur

Abigail said:
By design, and documented. From perlop/Symbolic Unary Operators:

Unary "-" performs arithmetic negation if the operand is
numeric. If the operand is an identifier, a string con­
sisting of a minus sign concatenated with the identifier
is returned. Otherwise, if the string starts with a plus
or minus, a string starting with the opposite sign is
returned. One effect of these rules is that -bareword is
equivalent to "-bareword".

I don't read it that way. For what I see,

-force

is the same as

"-" . force

It is not. Well, it is is, more or less, without use strict.

use strict; $_ = -force; print;
result:
-force

No error, no warning


$_ = "-" . force; print;
result:
Unquoted string "force" may clash with future reserved word at..
-force

No error, but a warning.

use strict; $_ = "-" . force; print;
result:
Bareword "force" not allowed while "strict subs" in use at...
Execution of test.pl aborted due to compilation errors.
 
P

Paul Lalli

Bart Lateur said:
I don't read it that way. For what I see,

-force

is the same as

"-" . force

Your interpretation is simply *not* what the documentation says. Read
it again. Very specifically, it says:

One effect of these rules is that -bareword is equivalent to
"-bareword".

It does NOT say that

One effect of these rules is that -bareword is equivalent to "-" .
bareword.

Obviously, the two statements are not one and the same. This fact is
proven by the very example you gave:
use strict; $_ = -force; print;
result:
-force

No error, no warning

Exactly as the documentation says it should work.
$_ = "-" . force; print;
result:
Unquoted string "force" may clash with future reserved word at..
-force

No error, but a warning.

use strict; $_ = "-" . force; print;
result:
Bareword "force" not allowed while "strict subs" in use at...
Execution of test.pl aborted due to compilation errors.

Exactly. because "-" . bareword is simply not equivalent to
"-bareword". Not in the documentation, and not in actual code.


Paul Lalli
 
J

Joe Smith

Brian said:
Hmmm... I suspect "by design" is a little too strong.

That's an insult to the group that created this feature.
If you want to use the fact that the current behaviour matches the
documented behaviour as justification that something's not a bug then
perhaps I should point out that the actual behaviour does not match the
above documentation fragment!

sub foo { 'bar' };
print -foo;

The above prints '-bar' not '-foo' and also emits a warning even without
"use warnings" in effect.

In that case, foo is _not_ a bareword; it is a function name.

A bareword is string that does not match any built-in or user-defined
function. Note where it says "If the operand is an identifier".
A string of alphanumeric characters may or may not be and identifier
depending on what has been previously defined.

It's all about context - the way that Perl parses each line can be
influenced by what precedes it.

-Joe
 
B

Brian McCauley

Joe said:
That's an insult to the group that created this feature.

No it is not.

In Perl, some features come about as a direct consequence of design
decision, others by implementational artifacts. Some of the features
that arose as implementational artifact get documented. Some don't.

All I said was that I suspected that this feature was one that as
implementational artifact.

Now first let's be 100% sure we know what feature we are talking about
here. The feature that is the pimary topic of this thread, and the one
I am talking about is the fact that the -bareword construct is exempt
from 'strict subs'. If you are talking about any other feature then you
are in the wrong thread.
In that case, foo is _not_ a bareword; it is a function name.

I know that, but that it is not relevant. The issue is not whether foo
is a bareword but whether it is an identifier. A function name surely
is an identifier.
A bareword is string that does not match any built-in or user-defined
function.

Well not just any string it has to be a syntactically valid identifier.
Note where it says "If the operand is an identifier".
A string of alphanumeric characters may or may not be and identifier
depending on what has been previously defined.

So you are saying that barewords are not identifiers. OK, in that case
the documentation fragment under discussion is even more erroneous than
I claimed it was since it clearly uses the term "indentifier" to refer
to a bareword.
It's all about context - the way that Perl parses each line can be
influenced by what precedes it.

I know that too. But this, too, is not relevant here.
 
A

Andrew Hamm

Bart said:
You're missing the point.

use strict; print -force

prints:

-force

both in 5.6.1 as in 5.8.3. For some reason, strict seems to be too
relaxed here. Maybe that is by design too, to allow for emulation of
named parameters more easily.

No, the point being missed is that

-identifier

is a string literal. Literally. It's just another form of "-identifier".
Strings do not have to be represented only by wrapping them in quotes.
 
A

Andrew Hamm

Bart said:
I don't read it that way. For what I see,

I can see how the statement could be called ambiguous:

"if the operand is an identifier, a string consisting of a minus sign
concetenated with the identifier is returned"

'returned' implies to some minds that a runtime activity is going on. But
actually, it's really implying that the lexer is "returning" a string that
has value "-identifier".

Perhaps this paragraph could benefit from some extremely careful editing.
Still, -identifier is definitely by design, and very useful.
 
A

Andrew Hamm

Brian said:
sub foo { 'bar' };
print -foo;

The above prints '-bar' not '-foo' and also emits a warning even
without "use warnings" in effect.

yeah, it says:

Ambiguous use of -foo resolved as -&foo() at ......

because it is, unfortunately, ambiguous. Because the compiler makes a
decision on your behalf, it MUST issue a warning when it could so easily
be intended that a literal "-foo" is desired. This Is A Good Thing, this
un-asked-for warning.

Change that line to

print - foo;

and the ambiguity goes away, and so does the warning.

Just because you can ask for more warnings with -w or "use warnings" does
not imply that there should be a complete absence of warnings when you
don't ask for them.
 
A

Andrew Hamm

Brian said:
Now first let's be 100% sure we know what feature we are talking about
here. The feature that is the pimary topic of this thread, and the
one I am talking about is the fact that the -bareword construct is
exempt from 'strict subs'. If you are talking about any other
feature then you are in the wrong thread.

Yes - everyone is talking about that. All will agree.

The important point to note is that BY DESIGN,

-identifier

is another form of string literal. It's just as "by design" as "string"
'string' qq(string) and <<TOKEN ..... TOKEN

-identifier is a string literal. By Design.

Because it *can* be ambiguous IF a sub called identifier is designed, the
builders of the parser have very thoughtfully given us a free warning that
will probably save your bacon one day.
 
A

Andrew Hamm

Abigail said:
%%
%% because it is, unfortunately, ambiguous. Because the compiler
makes a %% decision on your behalf, it MUST issue a warning when it
could so easily %% be intended that a literal "-foo" is desired.
This Is A Good Thing, this %% un-asked-for warning.

No, it's not. Unasked for warnings are as welcome as unasked for
system crashes.

well, this made me chuckle. I won't try to convince you otherwise. Hell,
why not - this is c.l.p.misc and discussion descending into flames is par
for the course. Let's see if we can at least stay above flames even if we
don't end up agreeing...

I think this warning is borderline as an error. Perhaps you'd feel more
confident if this compiler error was promoted to a compilation-halting
error? That way there'd be one less "unwanted warning". I expect the
author/designer of this warning figured that the programmer could benefit
from allowing the script to proceed since they will be able to
disambiguate the statement the next time they edit. I for one would
appreciate the opportunity to find more than one error as I'm developing a
script.

the case

sub foo { .... }
print -foo;

unfortunately leads to an ambiguity, so the only ultimate answer is to
remove the ambiguity in the Perl syntax? but then, would it still be Perl?

I'm hard-pressed to think of any unwanted warnings from Perl that
persistently shit me.
Yes, there should, IMO. I really, really loathe warnings I can't
turned off. It's so unperl. *I*, the programmer, and only *I* should
be in control - and never ever the compiler/language.

Sometimes the compiler needs your help to understand your code. In the
sample given,

sub foo { ... }
print -foo;

how pissed off would you be if you REALLY wanted it to mean

print "-foo";

But when you see this friendly warning, you can edit to correct. If you
really meant "-foo" then I suppose there are grounds to whinge about being
unable to use the -foo literally. I can agree with that...

Damn. A grey area in Perl. Who'd have thunk it?
 
M

Matt Garrish

Andrew Hamm said:
I'm hard-pressed to think of any unwanted warnings from Perl that
persistently shit me.

If you want to sound like a number of other chuckle-heads that post here
feel free to continue swearing, but it doesn't reflect well on you when you
do.

Matt
 
P

Peter Scott

Andrew Hamm ([email protected]) wrote on MMMMCXLIV September MCMXCIII in
<URL:%% Brian McCauley wrote:
%% >
%% > sub foo { 'bar' };
%% > print -foo;
%% >
%% > The above prints '-bar' not '-foo' and also emits a warning even
%% > without "use warnings" in effect.
%%
%% yeah, it says:
%%
%% Ambiguous use of -foo resolved as -&foo() at ...... [snip]
I really, really loathe warnings I can't turned
off. It's so unperl. *I*, the programmer, and only *I* should be in
control - and never ever the compiler/language.

You can turn the warning off:

% perl -le 'no warnings; sub foo { "bar" } print -foo'
-bar
%
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,440
Latest member
YoungBorel

Latest Threads

Top