develooper Front page | perl.perl5.porters | Postings from May 2012

[perl #96006] Some unary functions accept multiple arguments

Thread Next
Father Chrysostomos via RT
May 12, 2012 12:10
[perl #96006] Some unary functions accept multiple arguments
Message ID:
On Sun Jul 31 13:54:42 2011, sprout wrote:
> perl56delta has this section:
>    Better syntax checks on parenthesized unary operators
>        Expressions such as:
>            print defined(&foo,&bar,&baz);
>            print uc("foo","bar","baz");
>            undef($foo,&bar);
>        used to be accidentally allowed in earlier versions, and
>    produced
>        unpredictable behaviour.  Some produced ancillary warnings when
>    used in
>        this way; others silently did the wrong thing.
>        The parenthesized forms of most unary operators that expect a
>    single
>        argument now ensure that they are not called with more than one
>        argument, making the cases shown above syntax errors.  The
>    usual
>        behaviour of:
>            print defined &foo, &bar, &baz;
>            print uc "foo", "bar", "baz";
>            undef $foo, &bar;
>        remains unchanged.  See perlop.
> A few of unary functions survived, though:
> prototype(1,2,3) evaluates 1 and 2 in void context, using 3 (in scalar
>    context) as its argument. That’s harmless, although a bit
>    surprising. eval() behaves the same way.

I’ve been thinking about this on and off for some time.

!($foo, $bar) evaluates $foo in void context and $bar in scalar context.
 If we were to change that to ‘too many arguments for !’, we would have
a lynch mob after us.

The same applies to not($foo, $bar) and scalar($foo, $bar).

So I’ve been wondering why chr and getprotobynumber (for example) need
to refuse more than one argument.  How are these fundamentally different
from not and scalar?

If I get a void warning when writing scalar(3, foo()), isn’t that
sufficient for other ops as well?

Now, there is one case where it makes sense to refuse more than one
argument: scalar lvalue context.

I’m using the term lvalue in the broad sense of anything that goes
through op_lvalue internally, which means anything with a prototype
containing \$, \[$@%&*] or \[$@%*], or that parses as though it had such
a prototype.

In the case of untie(%foo,%bar), it is completely counterintuitive that
%bar should be untied, but not %foo.  So in this case it makes sense to
refuse more than one argument (which doesn’t currently happen).

What I propose we do is make built-in functions with a prototype (or
effective prototype) of ($), (;$), (*), (;*) or (_) allow more than one
argument, but treat it as a single scalar expression (i.e., with a
scalar comma); and make built-in functions with a(n effective) prototype
of (\$), (\[$@%*]), etc. refuse more than one argument.

Now, should the laxity regarding ($) apply to user-defined subroutines, too?


Father Chrysostomos

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About