Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Mixing named and positional values

25 views
Skip to first unread message

Patrick R. Michaud

unread,
May 26, 2008, 4:46:15 PM5/26/08
to parrot-...@perl.org
PDD03 currently says:

: =head3 Mixing named and positional values
:
: Positional targets can only be filled with positional values.
:
: Named targets can be filled with either positional or named values.
: However, if a named target was already filled by a positional value, and
: then a named value is also given, this is an overflow error.

This causes a bit of a problem for rakudo, because there's not
a way to specify that a named target is to be filled only by a
named value. In other words, the Perl 6 code

sub foo(:$a) { say $a; }

can't be easily represented in Parrot without resorting to using
slurpy targets and a variety of manipulations at the beginning of
the sub.

I'm also having trouble imagining a situation where we would
want a named target to be filled by a positional value in
preference to an explicitly named one -- i.e., I haven't
come up with a good use for the current semantics. (It's possible
I'm too perl6-biased at the moment to see the purpose.)

What I'd like to see is that a named target be filled only
by a named value, and have a flag that says that a named parameter
can also be filled by a positional if a corresponding named value
is not available(*). Filling of any non-named slurpy parameter
would come from any positional parameters after unnamed and
named positionals are filled.

With this we'd be able to implement Perl 6 parameters as follows:

## sub foo($a) { ... }
.param pmc param_a :positional :named('a')

## sub foo($a?) { ... }
.param pmc param_a :positional :named('a') :optional

## sub foo(:$a) { ... }
.param pmc param_a :named('a') :optional

## sub foo(:$a!) { ... }
.param pmc param_a :named('a')

I can also provide other Perl 6 to PIR examples if needed.

At this point I just need to know a general sense of how Parrot's
design will likely proceed on this. If the current implementation
isn't likely to change anytime soon, then I'll go ahead and
start making (some potentially messy) workarounds in Rakudo and
the compiler tools.

Pm


(*) Note that this is not what PDD03 specifies now, which fills
a named target with a positional and then carps if a named
value is also given.


Allison Randal

unread,
May 28, 2008, 8:22:37 PM5/28/08
to Patrick R. Michaud, parrot-...@perl.org
(After talking about it on the phone today.) From the Parrot side, we
have basically 3 binary factors: named (or not), positional (or not),
and optional/required.

The unmarked case is a required parameter that can be passed as a
positional argument and can't be passed as a named argument. (Perl 6
doesn't use this at all, but other languages do.)

.param pmc param_a

The next case is a required parameter that can only be passed as a named
argument, not as a positional argument. (Essentially an optimization,
also used by Perl 6.)

.param pmc param_a :named('a')

The next case is a required parameter that can be passed as either
positional or named. For each positional parameter, the signature
binding code first checks if there is a matching named argument before
binding a positional argument to the parameter. (The necessary essential
core to support the Perl 6 semantics, though Perl 6 adds dose or two of
syntactic sugar on top.)

.param pmc param_a :lookahead('a')

The logical final case, which we won't support now but could add later,
can also be passed as either positional or named, but the signature
binding code doesn't bother looking at named arguments until it runs out
of positional arguments. This has some interest as an optimization, but
we don't have a clear immediate need for it in any language, so at the
moment it's unnecessary complexity and a premature optimization.


Any of these alternatives can be marked as optional. Positional
parameters must come before all lookahead or named parameters. Lookahead
parameters must come before all named parameters. Positional, lookahead,
and named parameters must come before any slurpy parameters. And
required parameters must come before all optional parameters.

Allison

Bob Rogers

unread,
May 28, 2008, 10:05:32 PM5/28/08
to Allison Randal, Patrick R. Michaud, parrot-...@perl.org
From: Allison Randal <all...@perl.org>
Date: Thu, 29 May 2008 02:22:37 +0200

. . .

Any of these alternatives can be marked as optional. Positional
parameters must come before all lookahead or named parameters. Lookahead
parameters must come before all named parameters. Positional, lookahead,
and named parameters must come before any slurpy parameters. And
required parameters must come before all optional parameters.

Allison

These ordering constraints could be summarized as follows:

positional < lookahead < named
required < optional

I assume you meant "order by positionality, then by optionality";
otherwise, ordering a required named parameter vs. an optional
positional parameter would be tough. That yields the following
declaration order (ignoring :slurpy):

Pos? Named? Reqd? => Example
yes no yes => .param pmc A
yes no no => .param pmc B :optional
yes yes yes => .param pmc C :lookahead('c')
yes yes no => .param pmc D :optional :lookahead('d')
no yes yes => .param pmc E :named('e')
no yes no => .param pmc F :optional :named('f')

I can see why B has to be after A and before C, and I assume ":lookahead
before :named" makes the implementation easier, but I can't see the need
for any particular ordering of C vs. D, or E vs. F. Am I missing
something? Just curious,

-- Bob Rogers
http://rgrjr.dyndns.org/

Patrick R. Michaud

unread,
May 29, 2008, 12:14:06 AM5/29/08
to Bob Rogers, Allison Randal, parrot-...@perl.org
On Wed, May 28, 2008 at 10:05:32PM -0400, Bob Rogers wrote:
> From: Allison Randal <all...@perl.org>

> >
> > Any of these alternatives can be marked as optional. Positional
> > parameters must come before all lookahead or named parameters. Lookahead
> > parameters must come before all named parameters. Positional, lookahead,
> > and named parameters must come before any slurpy parameters. And
> > required parameters must come before all optional parameters.

Note that "Positional, lookahead, and named parameters must come before
any slurpy parameters" is a significant change from the existing
spec, which allows slurpy positionals to appear before named parameters.
In fact, PDD03 seems to require this (although Parrot currently does not):

PDD03> So the acceptable ordering of targets is:
PDD03> * positional non-SLURPY (any number)
PDD03> * positional SLURPY array (optional)
PDD03> * NAMED non-SLURPY (any number)
PDD03> * NAMED SLURPY hash (optional)

Since there's a fair amount of existing code that may be doing
slurpy positionals before named parameters, I propose, perhaps
as an interim step, that we say that positional slurpy array
parameters must come after all positional and lookahead parameters
(but could come before the named parameters), and any slurpy hash
must come after all lookahead and named parameters. This would
allow existing code to work while still preserving the proper
binding sequence.

> These ordering constraints could be summarized as follows:
>
> positional < lookahead < named
> required < optional
>
> I assume you meant "order by positionality, then by optionality";
> otherwise, ordering a required named parameter vs. an optional
> positional parameter would be tough. That yields the following
> declaration order (ignoring :slurpy):
>
> Pos? Named? Reqd? => Example
> yes no yes => .param pmc A
> yes no no => .param pmc B :optional
> yes yes yes => .param pmc C :lookahead('c')
> yes yes no => .param pmc D :optional :lookahead('d')
> no yes yes => .param pmc E :named('e')
> no yes no => .param pmc F :optional :named('f')
>
> I can see why B has to be after A and before C, and I assume ":lookahead
> before :named" makes the implementation easier, but I can't see the need
> for any particular ordering of C vs. D, or E vs. F. Am I missing
> something? Just curious,

C needs to come before D because all required positionals need to be
filled before we get to the optional ones. In fact, I think that
B and C should be switched above, so that required lookaheads are
filled before optional positionals. Otherwise we can end up with
a situation where a required lookahead cannot be filled because
the value was given to an optional positional.

OTOH, I don't know that there will be many situations where
positionals and lookaheads are combined, so it may not be an
important issue. (And one can always "fix" things by converting
positionals into lookaheads with dummy names if an ordering needs
to preserved among the mixture.)

I agree that the ordering of E and F doesn't really matter to
any of the above -- for named only parameters the binding sequence
isn't important.

So my version of the above might be:

Pos? Reqd? Named? => Example
yes yes no => .param pmc A
yes yes yes => .param pmc B :lookahead('b')
yes no no => .param pmc C :optional
yes no yes => .param pmc D :optional :lookahead('d')


no yes yes => .param pmc E :named('e')

no no yes => .param pmc F :optional :named('f')

with :slurpy array occurring anytime after D, and :slurpy :named
hash occurring after F.

Pm

Allison Randal

unread,
May 29, 2008, 4:42:31 AM5/29/08
to Patrick R. Michaud, Bob Rogers, parrot-...@perl.org
Patrick R. Michaud wrote:
>
> Since there's a fair amount of existing code that may be doing
> slurpy positionals before named parameters, I propose, perhaps
> as an interim step, that we say that positional slurpy array
> parameters must come after all positional and lookahead parameters
> (but could come before the named parameters), and any slurpy hash
> must come after all lookahead and named parameters. This would
> allow existing code to work while still preserving the proper
> binding sequence.

It's tricky to decide where to put the positional slurpy with the
addition of lookaheads, which can be either named or positional, because
it won't slurp up the remaining positional arguments until they've been
bound to the lookahead parameters.

That would imply an ordering of:

* positional non-SLURPY (any number)

* lookahead non-SLURPY (any number)


* positional SLURPY array (optional)

* NAMED non-SLURPY (any number)

* NAMED SLURPY hash (optional)

Though, really there's no reason to require that the positional slurpy
come before named non-slurpy. So, let's relax the constraint and just
say "the positional slurpy must follow all other positional parameters
(including lookaheads)" and "the named slurpy must follow all other
named parameters (including lookaheads)".

Since we'll have to transition :named to :lookahead in many cases (in
whatever branch this is developed in), it shouldn't be much extra effort
to double check and make sure that any positional :slurpy parameters
also follow the :lookahead parameters.

> C needs to come before D because all required positionals need to be
> filled before we get to the optional ones. In fact, I think that
> B and C should be switched above, so that required lookaheads are
> filled before optional positionals. Otherwise we can end up with
> a situation where a required lookahead cannot be filled because
> the value was given to an optional positional.

Yes, you have to bind all required positional parameters before you bind
any optional parameters.

For any parameters that can be filled positionally, you can switch from
required to optional exactly once, and switch from positional to
lookahead exactly once, so you can switch to optional within the
lookahead parameters:

.param pmc A


.param pmc B :lookahead('b')

.param pmc C :optional :lookahead('c')

Or switch to optional within the positional parameters, in which case
all the lookahead parameters must also be optional:

.param pmc A
.param pmc B :optional
.param pmc C :optional :lookahead('c')


.param pmc D :optional :lookahead('d')

But you can never switch to optional in the positional parameters and
then switch back to required in the lookahead parameters:

.param pmc A
.param pmc B :optional
* .param pmc C :lookahead('c') # syntax error


.param pmc D :optional :lookahead('d')

And you can never switch back to positional parameters after switching
to lookahead parameters.

.param pmc A


.param pmc C :lookahead('c')

* .param pmc B :optional # syntax error


.param pmc D :optional :lookahead('d')

> OTOH, I don't know that there will be many situations where


> positionals and lookaheads are combined, so it may not be an
> important issue. (And one can always "fix" things by converting
> positionals into lookaheads with dummy names if an ordering needs
> to preserved among the mixture.)

And, yes, there are options for munging the parameters otherwise if a
language has really complex parameter syntax.

Basically, pure positional parameters are a "strip out all the frills"
optimization. The argument binding code can always stupidly bind
positional arguments to positional parameters, one at a time, until it
runs out of arguments or runs out of pure positional parameters. It will
only pay attention to lookahead or named parameters once it's done with
pure positionals.

> I agree that the ordering of E and F doesn't really matter to
> any of the above -- for named only parameters the binding sequence
> isn't important.

And agreed that the ordering of the named-only parameters doesn't really
matter, but for code maintenance sanity and possible future
optimizations, let's say that required named-only parameters must come
before optional named-only parameters.

Allison

Bob Rogers

unread,
May 30, 2008, 8:59:23 PM5/30/08
to Patrick R. Michaud, Allison Randal, parrot-...@perl.org
From: "Patrick R. Michaud" <pmic...@pobox.com>
Date: Wed, 28 May 2008 23:14:06 -0500

On Wed, May 28, 2008 at 10:05:32PM -0400, Bob Rogers wrote:
> Pos? Named? Reqd? => Example
> yes no yes => .param pmc A
> yes no no => .param pmc B :optional
> yes yes yes => .param pmc C :lookahead('c')
> yes yes no => .param pmc D :optional :lookahead('d')
> no yes yes => .param pmc E :named('e')
> no yes no => .param pmc F :optional :named('f')
>
> I can see why B has to be after A and before C, and I assume ":lookahead
> before :named" makes the implementation easier, but I can't see the need
> for any particular ordering of C vs. D, or E vs. F. Am I missing
> something? Just curious,

C needs to come before D because all required positionals need to be
filled before we get to the optional ones.

But there are two ways to fill a :lookahead positional . . .

================
From: Allison Randal <all...@perl.org>
Date: Thu, 29 May 2008 10:42:31 +0200

. . .

But you can never switch to optional in the positional parameters and
then switch back to required in the lookahead parameters:

.param pmc A
.param pmc B :optional

* .param pmc C :lookahead('c') # syntax error


.param pmc D :optional :lookahead('d')

Hmm. Seems to me that a minimal call to this sub could look like:

foo(1, :c(3));

which (if I haven't butchered the P6 syntax) would bind A to 1 and C to
3, leaving B and D unbound. I don't have a real use case for this,
though.

And agreed that the ordering of the named-only parameters doesn't
really matter, but for code maintenance sanity and possible future
optimizations, let's say that required named-only parameters must
come before optional named-only parameters.

Allison

Sounds reasonable.

-- Bob

0 new messages