My Favorite Warnings: ambiguous

... computer language design is just like a stroll in the park. Jurassic Park, that is. -- Larry Wall

Perl's grammar is inherently ambiguous. That is, it is possible for a syntactically correct chunk of Perl to have more than one valid interpretation. Maybe this is because Larry Wall is a linguist? After all, natural languages are full of ambiguity.

The ambiguous warning is part of the group syntax; that is to say, use warning 'syntax'; enables ambiguous, as well as other warnings in that group. Of course, if appropriate you can just use warning 'ambiguous'; if more precision is justified. Both warnings go back to Perl 5.6, when the warnings pragma itself was introduced.

As has become habitual, I present a random selection of instances of this warning. Normal text is from perldiag. Italicized text is mine.

Ambiguous call resolved as CORE::%s(), qualify as such or use &

You declared a subroutine whose name conflicts with a built-in. The diagnostic covers most ways to deal with this, but not the obvious one: rename your own subroutine.

Ambiguous use of %c{%s} resolved to %c%s (e.g. @{foo} resolved to @foo)

Ambiguous use of %c{%s[...]} resolved to %c%s[...] (e.g. ${foo[2]}, where foo is a Perl keyword)

Ambiguous use of %c{%s{...}} resolved to %c%s{...} (ditto)

All of these involve a sigil in front of curly brackets that enclose a bareword, maybe with trailing subscript-like things. If both a variable and a subroutine exist with the given name, Perl does not know whether you want to refer to the variable or call the subroutine and dereference its result. The second diagnostic also involves the ambiguity between array subscripts and anonymous array constructors. The last diagnostic involves the ambiguity between hash subscripts and anonymous hash constructors.

Possible unintended interpolation of $\ in regex

This is tricky, because although $\ is the output record separator, in a regex $ means end-of-line, and \ either creates or escapes a metacharacter. If you actually mean to interpolate $\, turn off the warning. If you mean to assert end-of-line followed by a back slash, the diagnostic recommends interposing the no-op (?), which changes the modifiers in effect but does not specify any modifiers. That is, write / ... $(?)\ ... / instead of / ... $\ ... /.

Not all ambiguities are covered by this warning. The following causes me trouble fairly regularly. I am sure there are others.

Blocks versus anonymous hash constructors

Both are { ... }, and Perl has heuristics that usually get it right. But if they get it wrong strange things can happen. You can force interpretation as an anonymous hash by prefixing a unary plus: +{ ... }. If you want a block, follow the opening curly with a semicolon: {; ... }.

Previous entries in this series:

  1. A Belated Introduction
  2. once
  3. redundant and missing
  4. exiting
  5. uninitialized
  6. redefine
  7. Ex-Warnings
  8. deprecated
  9. experimental
  10. shadow
  11. syntax

1 Comment

Brilliant, thanks very much.

The work-arounds for disambiguating are particularly helpful.

Leave a comment

About Tom Wyant

user-pic I blog about Perl.