Demagicalizing pairs

1 view
Skip to first unread message

Luke Palmer

unread,
Aug 19, 2005, 6:31:34 AM8/19/05
to Perl6 Language List
We've seen many problems come up with the current special treatment of
pairs. Here's what I can think of:

* Pairs are restricted to a particular position in the argument list, which
leads to confusion (why isn't this being passed named?) and poor
end-weight in something like this:

foo {
# lots of code in here
# blah blah blah
...
} :delay(1)

which would probably be more readable with :delay(1) up at the top

* We had to special-case pointy blocks not to take named arguments because
of this construct:

for %hash.pairs -> $pair { ... }

* (IIRC) We still have to scan potentially infinite lists when using the
foo(*@args) caller-side flattening form.

I propose that we move the magic out of the Pair type, and into a
syntactic form. Here's the best we have (from #perl6) at the moment:

a => b # always a plain-vanilla pair, never a named argument
:a(b) # always a named argument (in sub calls)
# degenerates to a plain pair when not in a sub call
named(a => b) # make an ordinary pair (or list of pairs) into
# runtime named arguments
named(%named) # same

This has a couple of advantages. First of all, in the call:

foo($a, $b, $c)

You *know* that you're passing three positionals. It looks like what
it is. Also, you don't have to take extra cautionary measures if
you're dealing with generic data.

It's much less work for the runtime. You don't have to scan for
pairs, you just have the caller stuff them where you need them.

You only lose a *little* bit of flexibility at a great gain of
usability of pairs. That little bit is this ability:

my @args = (1, 2, 3, foo => 'bar');
baz(*@args); # $foo gets argument 'bar'

And yet, you can fudge that back in on the callee side:

sub baz (*@args) {
my (@pos, %named);
for @args {
when Pair { $named{.key} = .value; }
default { push @pos: $_ }
}
real_baz(*@args, named(%named))
}

And you lose the ability to pretend that you're taking named arguments
when you're not; that is, you say you're not being order dependent
when you are.

I think this is fixable with a trait on the sub:

sub form (*@args) is unnameable # refuse named parameters altogether
{ }

Anything more magical than that can be dealt with explicitly.

Luke

Larry Wall

unread,
Aug 19, 2005, 11:27:38 AM8/19/05
to Perl6 Language List
On Fri, Aug 19, 2005 at 10:31:34AM +0000, Luke Palmer wrote:
: I propose that we move the magic out of the Pair type, and into a
: syntactic form.

That's kinda the direction we were already moving with the *%foo proposal,
so I think I like it, but I'll need to steep my brain in a bit more caffeine.

: Here's the best we have (from #perl6) at the moment:


:
: a => b # always a plain-vanilla pair, never a named argument
: :a(b) # always a named argument (in sub calls)
: # degenerates to a plain pair when not in a sub call
: named(a => b) # make an ordinary pair (or list of pairs) into
: # runtime named arguments
: named(%named) # same

Offhand I don't like the name of named(). Actually, it's kind of a shame
we've already used :() for sigs, since we could say that :a(b) is :(a=>b).
Damian had a proposal at our meeting to demote sigs to methods, but
I've forgotten (or at least, haven't remembered) why that didn't fly.
Probably something about having to at least be a macro because the
parser has to start out at a different state inside.

Plus I still think it's a really bad idea to allow intermixing of
positionals and named. We could allow named at the beginning or end
but still keep a constraint that all positionals must occur together
in one zone.

: This has a couple of advantages. First of all, in the call:


:
: foo($a, $b, $c)
:
: You *know* that you're passing three positionals. It looks like what
: it is. Also, you don't have to take extra cautionary measures if
: you're dealing with generic data.
:
: It's much less work for the runtime. You don't have to scan for
: pairs, you just have the caller stuff them where you need them.

We already had it as pure syntax with the * proposal, albeit with the
=> still indicating named args.

: You only lose a *little* bit of flexibility at a great gain of


: usability of pairs. That little bit is this ability:
:
: my @args = (1, 2, 3, foo => 'bar');
: baz(*@args); # $foo gets argument 'bar'

I suspect a lot of people would still prefer to write named args with =>,
so we should put some thought into making it syntactically trivial, if
not automatic like it is now. Even making named() a listop would help.
I guess a downside to stealing :() is that it doesn't listopify readily,
and if you tried to, it would look weird, and you'd have to leave a
space after it.

my @args = (1, 2, 3, :(foo => 'bar'));


my @args = (1, 2, 3, : foo => 'bar');

Pity this doesn't work:

my @args = (1, 2, 3, [:] foo => 'bar');

Maybe "where" as a term would work

my @args = (1, 2, 3, where foo => 'bar');

Nah, people would omit the last comma and wonder why it's trying to
subtype 3. Hmm.

my @args = (1, 2, 3, plus foo => 'bar');

Assuming we stick with the + marker...

...since another little niggly inconsistency is that we'd be marking
named params with : on the call side but + on the receiving side.
I hate to say it, but the named args should probably be marked
with : instead of + in the signature. Not sure what that does to
invocant colon though. Probably requires that sigs with an explicitly
unnamed invocant start ($:...) or (Type:...) rather than just (:...).
Maybe that's not terribly important, since most invocants are either
entirely there or entirely missing.

: And you lose the ability to pretend that you're taking named arguments


: when you're not; that is, you say you're not being order dependent
: when you are.
:
: I think this is fixable with a trait on the sub:
:
: sub form (*@args) is unnameable # refuse named parameters altogether

: { }

More likely a trait on the slurpy. Or maybe there's still room for
a type wider than Item on the slurpy array. In either case it would
imply some kind of logic in argument unpacking that says, "I don't
have a place for named arguments, so splice any named list on the front
of the slurpy list." Offhand I don't see a problem with that approach.

On the other hand, how else is the default p5-ish *@_ going to behave
when there's no sig? (Though it's still a problem for methods that
generate *%_ for you, so we still need some explicit way to control
it on explicit slurpies.)

One other idle thought is that, if we don't mind blowing a different
kind of consistency, and if we s/+/:/ in sigs, a sig containing
:$foo could instead be written $:foo (presuming we take : away from
privates as we've postulated), which would get the colon next to the
name and have better visual correspondence with the :foo(), syntax,
and maybe even allow adverbs to include an optional sigil on the front.
On the other hand, then people would want to write $:foo in the body,
and that won't do. So nevermind. Stick with :$foo for that.

Larry

Yuval Kogman

unread,
Aug 19, 2005, 11:30:41 AM8/19/05
to Luke Palmer, Perl6 Language List
On Fri, Aug 19, 2005 at 10:31:34 +0000, Luke Palmer wrote:

In short, "me too".

Now some comments:

> foo($a, $b, $c)
>
> You *know* that you're passing three positionals.

This is very very important for least surprise and all that.

> It's much less work for the runtime. You don't have to scan for
> pairs, you just have the caller stuff them where you need them.

This will also allow more static binding of named parameters, which
is a good thing, because it will simplify the type inferencer code.

> You only lose a *little* bit of flexibility at a great gain of
> usability of pairs. That little bit is this ability:
>
> my @args = (1, 2, 3, foo => 'bar');
> baz(*@args); # $foo gets argument 'bar'

To be honest, I don't see how that is a feature, this strengthens my
support for demagicalizing.

--
() Yuval Kogman <nothi...@woobling.org> 0xEBD27418 perl hacker &
/\ kung foo master: /me climbs a brick wall with his fingers: neeyah!

Larry Wall

unread,
Aug 19, 2005, 11:39:24 AM8/19/05
to Perl6 Language List
Hmm, if we take + away from named, it can become the "required" marker,
so

sub foo ($a,$b,?$c)

is really short for

sub foo (+$a,+$b,?$c)

and required named parameters then become

sub bar (+:$key)

And, of course, that means that

sub baz (+?$key)

is a required optional parameter. :-)

Actually, that's an argument that : is in a different class than the regex
quantifiers, and required named should be

sub bar (+$:key)

as I speculated earlier. Maybe we just force that to bind to $key instead
of $:key. That screws up the

submethod BUILD ($.attribute)

syntax though, unless we say that any twigil forces named argument passing,
or otherwise just force it to work. Though with BUILD we've basically
said already that all arguments must be passed +$: (required name) form.

Maybe it can be made to work.

Larry

Yuval Kogman

unread,
Aug 19, 2005, 11:42:04 AM8/19/05
to Perl6 Language List
On Fri, Aug 19, 2005 at 08:27:38 -0700, Larry Wall wrote:

> Plus I still think it's a really bad idea to allow intermixing of
> positionals and named. We could allow named at the beginning or end
> but still keep a constraint that all positionals must occur together
> in one zone.

This is something I think code style should take care of.

I would probably put all of my named "nouns" in the begining,
positional nouns after that, and named adjectives at the end,
because that's usually their order of importance for me.

If there is some really odd code signature which takes in a mess, I
may want to intermix positionals and named's in order to increase
readability.

In both these scenarios I see no use in the language limiting me
"just because"... I think this is a reiteration of the "I'm not
stupid, Perl should give me credit" issue.

> ...since another little niggly inconsistency is that we'd be marking
> named params with : on the call side but + on the receiving side.
> I hate to say it, but the named args should probably be marked
> with : instead of + in the signature.

I agree

> Not sure what that does to
> invocant colon though.

Invocant colon as a metaphor is nice for

method $object : ....;

But I think that kinda sucks for

new Dog; # uh, didn't you mean 'new Dog:;'?

And I personally never ever liked it in in signatures.

I would much rather see it go away, frankly, and let the issues be
resolved by simplifying the OOP system. *cough*, *cough*.

--
() Yuval Kogman <nothi...@woobling.org> 0xEBD27418 perl hacker &

/\ kung foo master: uhm, no, I think I'll sit this one out..: neeyah!

Larry Wall

unread,
Aug 19, 2005, 11:52:21 AM8/19/05
to Perl6 Language List
On Fri, Aug 19, 2005 at 06:30:41PM +0300, Yuval Kogman wrote:

: On Fri, Aug 19, 2005 at 10:31:34 +0000, Luke Palmer wrote:
:
: In short, "me too".
:
: Now some comments:
:
: > foo($a, $b, $c)
: >
: > You *know* that you're passing three positionals.
:
: This is very very important for least surprise and all that.

Yes, that's why we were already syntacticalizing with the *%foo proposal.

: > It's much less work for the runtime. You don't have to scan for


: > pairs, you just have the caller stuff them where you need them.
:
: This will also allow more static binding of named parameters, which
: is a good thing, because it will simplify the type inferencer code.

That too.

: > You only lose a *little* bit of flexibility at a great gain of


: > usability of pairs. That little bit is this ability:
: >
: > my @args = (1, 2, 3, foo => 'bar');
: > baz(*@args); # $foo gets argument 'bar'
:
: To be honest, I don't see how that is a feature, this strengthens my
: support for demagicalizing.

Seems to me that the * processor could easily install a pair-to-named
promoter if that was deemed to be desirable. The * already says you're
cheating.

Alternately, instead of a normal list composer, have one that generates
a special list that is predigested into zones.

my @args := arglist(1, 2, 3, :foo('bar') <== @slurpme);
baz(*@args); # Just Works

Presumably we need that funny list type anyway to collect named vs
positionals vs slurpies at compile time, so all we need to do is
expose that type via arglist() or whatever we call it. Maybe it's just

my @args := ArgList.new(1, 2, 3, :foo('bar') <== @slurpme);

Doesn't have to be Huffshort.

Larry

Larry Wall

unread,
Aug 19, 2005, 1:01:18 PM8/19/05
to Perl6 Language List
On Fri, Aug 19, 2005 at 08:39:24AM -0700, Larry Wall wrote:
: Actually, that's an argument that : is in a different class than the regex

: quantifiers, and required named should be
:
: sub bar (+$:key)
:
: as I speculated earlier. Maybe we just force that to bind to $key instead
: of $:key.

Which makes me wonder whether, in ordinary code (not sigs)

$:key

is short for

:key($key)

The idea being that it makes it really easy to pass delegate particular
pairs to subfunctions as long as you keep the names consistent. It'd
also make it drop-dead easy to write positional-to-named constructors:

method new ($proto: $a, $b, $c) {
...
return $proto.bless($:a, $:b, $:c);
}

instead of

method new ($proto: $a,$b,$c) {
...
return $proto.bless(:a($a), :b($b), :c($c));
}

I suppose if we pushed it we could even allow $:foo in adverbial position.

1 .. 100 $:by

But I wonder if people will think that

foo 1, 2, 3, @:foo

should interpolate @foo as a list of pairs rather than binding to the
'foo' argument. Likewise for %:bar. But those are still *@foo and
*%bar, I suspect, and people can learn that the : twigil always means
rewrite. Hmm. That seems to indicate that the actual signature for
named parameters is

sub foo (:foo($foo))

and that

sub foo ($:foo)

is just shorthand for that. That would give us the ability to give the
variable a different name than the parameter. I like.

sub seek (:x($horizontal),:y($vertical))

On the other hand, it's now unclear whether you can call that as seek(1,2).
Needs to be allowed somehow.

Larry

Chip Salzenberg

unread,
Aug 21, 2005, 6:25:12 PM8/21/05
to Yuval Kogman, Perl6 Language List
On Fri, Aug 19, 2005 at 06:42:04PM +0300, Yuval Kogman wrote:
> If there is some really odd code signature which takes in a mess, I
> may want to intermix positionals and named's in order to increase
> readability.

AFAIR, named parameter syntax will work for positionals as well[*].
So even if you want to intermix the positional parameters with named,
there's no need for us to support intermixing positional parameter
*syntax* with named...?

/me relurks
--
Chip Salzenberg <ch...@pobox.com>

Eric

unread,
Aug 22, 2005, 12:51:25 PM8/22/05
to Perl6 Language List
Just my two cents then back to lurking. The idea of having named parameters
with different names than the variables ++. Otherwise your public API is
dependent on private variables which is a Bad Thing and the only thing that
realy bugged me about current named parameters in P6.

BTW why is it that just because they are defined as named they can't be used
positionaly as well?

Guess you could always use your same positional to named magic for the
positionals. Then the programmer is expliciting defining the order in case
the cases they want to use ordered versus named.

multi sub seek ( $x, $y ) { seek( $:x, $:y) }:
multi sub seek ( :x($horizontal), :y($vertical)) { ... };

--
__________
Eric Hodges

Larry Wall

unread,
Aug 22, 2005, 12:54:36 PM8/22/05
to Perl6 Language List
On Fri, Aug 19, 2005 at 06:42:04PM +0300, Yuval Kogman wrote:
: On Fri, Aug 19, 2005 at 08:27:38 -0700, Larry Wall wrote:
:
: > Plus I still think it's a really bad idea to allow intermixing of
: > positionals and named. We could allow named at the beginning or end
: > but still keep a constraint that all positionals must occur together
: > in one zone.
:
: This is something I think code style should take care of.
:
: I would probably put all of my named "nouns" in the begining,
: positional nouns after that, and named adjectives at the end,
: because that's usually their order of importance for me.

That's not a problem as long as you keep your positionals together.

: If there is some really odd code signature which takes in a mess, I


: may want to intermix positionals and named's in order to increase
: readability.

This is Perl 6, which means it'll be trivially easy to implement

no strict "positionals";

or whatever you want to call it.

: In both these scenarios I see no use in the language limiting me


: "just because"... I think this is a reiteration of the "I'm not
: stupid, Perl should give me credit" issue.

I think it's really easy for newbies to confuse themselves this way,
and that's where strictures are most useful.

: > ...since another little niggly inconsistency is that we'd be marking


: > named params with : on the call side but + on the receiving side.
: > I hate to say it, but the named args should probably be marked
: > with : instead of + in the signature.
:
: I agree
:
: > Not sure what that does to
: > invocant colon though.
:
: Invocant colon as a metaphor is nice for
:
: method $object : ....;
:
: But I think that kinda sucks for
:
: new Dog; # uh, didn't you mean 'new Dog:;'?

The colon makes no difference there.

: And I personally never ever liked it in in signatures.

The use of colon as the SMD invocant marker is actually just a
degenerate case of MMD tiebreaking syntax.

: I would much rather see it go away, frankly, and let the issues be


: resolved by simplifying the OOP system. *cough*, *cough*.

Well, I can see the appeal of optimizing for the implementor rather than
the user. A lot of languages have already tried that... :-)

On the other hand, I'm not all that attached to colon itself. If,
as proposed elsewhere, we get rid of the %Foo:: notation in favor of
some Foo<> variant, then trailing :: becomes available (ignoring ??/::
for the moment), and

new Dog:: tail => 'long'

almost makes sense, insofar as it kinda looks like it's marking Dog
as a type name, even though it isn't. But

new Dog:: :tail<long>

doesn't look so good.

On the other hand, looking at it from the other end, the MMD notation
tiebreaking notation is a little hard to spot, since colon is easy
to miss. Maybe there's something that shows up better in a signature
that also works as the invocant marker and, by extension, the indirect
object marker. Since it's an ordering kind of thing, you'd kind of
like to work > into it somehow, since the left side is of "greater"
importance than the left. Unfortunately, though, "the good ones are
all taken". Maybe some digraph like

method new ($what*> $:tail) {...}
method new ($what+> $:tail) {...}
method new ($what.> $:tail) {...}
method new ($what|> $:tail) {...}
method new ($what>> $:tail) {...}

giving

new Dog*> :tail<long>
new Dog+> :tail<long>
new Dog.> :tail<long>
new Dog|> :tail<long>
new Dog>> :tail<long>

I guess that last one is eqivalent to:

method new ($what» $:tail) {...}
new Dog» :tail<long>

which I could maybe get used to. It kind of looks like a prompt to me.

The ordinary MMD might look like

multi foo ($a, $b, $c» $d)

And Lisp-like MMD fallback on every argument would look like

multi foo ($a» $b» $c» $d»)

I suppose that particular use of » could be construed as encouraging
people not to do that. :-)

Larry

Larry Wall

unread,
Aug 22, 2005, 1:17:24 PM8/22/05
to Perl6 Language List
On Mon, Aug 22, 2005 at 10:51:25AM -0600, Eric wrote:
: Just my two cents then back to lurking. The idea of having named parameters
: with different names than the variables ++. Otherwise your public API is
: dependent on private variables which is a Bad Thing and the only thing that
: realy bugged me about current named parameters in P6.
:
: BTW why is it that just because they are defined as named they can't be used
: positionaly as well?

Because then the named marker would be redundant with the ? marker, which
can already be supplied as named parameters, as can mandatory positionals.

: Guess you could always use your same positional to named magic for the

: positionals. Then the programmer is expliciting defining the order in case
: the cases they want to use ordered versus named.
:
: multi sub seek ( $x, $y ) { seek( $:x, $:y) }:
: multi sub seek ( :x($horizontal), :y($vertical)) { ... };

Which would mean that :x() doesn't imply named-only, so we'd still need
a separate marker for that. But that seems like the wrong default.
And you can always alias the variable at the top of the body if you're
desperate for a different name than the public interface. Also, we'd
have to look at how these things degrade in partially specified stubs:

sub mystery { :x($), +:y(Dog @ where Beagle) }

It looks like it could get messy. Er, messier.

Larry

Yuval Kogman

unread,
Aug 22, 2005, 3:44:28 PM8/22/05
to Perl6 Language List
On Mon, Aug 22, 2005 at 09:54:36 -0700, Larry Wall wrote:
> That's not a problem as long as you keep your positionals together.

Oh, I assumed the it's

/(<named>* <positionals>*)|(<positionals>* <named>*)/,

not
/<named>* <positionals>* <named>*/


> : If there is some really odd code signature which takes in a mess, I
> : may want to intermix positionals and named's in order to increase
> : readability.
>
> This is Perl 6, which means it'll be trivially easy to implement
>
> no strict "positionals";
>
> or whatever you want to call it.

By the way, how does FFI relate to this? Say I'm calling a remote
function, like

use icky_language:SomePackage;

some_function( #not for the children );

> : new Dog; # uh, didn't you mean 'new Dog:;'?
>
> The colon makes no difference there.

Oops... Tee hee =)

> The use of colon as the SMD invocant marker is actually just a
> degenerate case of MMD tiebreaking syntax.

Again with the coughing

> : I would much rather see it go away, frankly, and let the issues be
> : resolved by simplifying the OOP system. *cough*, *cough*.
>
> Well, I can see the appeal of optimizing for the implementor rather than
> the user. A lot of languages have already tried that... :-)

My OOP simplification coughs were actually because I think the OOP
system is a little too complex for the user, not the implementor,
but I've brought that up enough times.

For the implementor SMD is just MMD with some constraints, so it's
really just an extension of the implementation, so I'm not worried
either way. If you're interested I can dig up a chat log where
autrijus and I argue over this a bit.

--
() Yuval Kogman <nothi...@woobling.org> 0xEBD27418 perl hacker &

/\ kung foo master: /me sushi-spin-kicks : neeyah!!!!!!!!!!!!!!!!!!!!

Damian Conway

unread,
Aug 24, 2005, 2:27:03 AM8/24/05
to Larry Wall, Perl6 Language List
Larry wrote:

> Plus I still think it's a really bad idea to allow intermixing of
> positionals and named. We could allow named at the beginning or end
> but still keep a constraint that all positionals must occur together
> in one zone.

If losing the magic from =>'d pairs isn't buying us named args wherever we
like, why are we contemplating it?


> I suspect a lot of people would still prefer to write named args with =>,

I'd say so.


> so we should put some thought into making it syntactically trivial, if
> not automatic like it is now. Even making named() a listop would help.

I'd say that's the best alternative. I'd certainly prefer that to repurposing
:(...)


> I hate to say it, but the named args should probably be marked
> with : instead of + in the signature.
>

> One other idle thought is that, if we don't mind blowing a different
> kind of consistency, and if we s/+/:/ in sigs, a sig containing
> :$foo could instead be written $:foo (presuming we take : away from
> privates as we've postulated),

Yes please. Underscore is much better in that role.

Damian

Damian Conway

unread,
Aug 24, 2005, 2:52:52 AM8/24/05
to Larry Wall, Perl6 Language List
Larry mused:

> On the other hand, I'm not all that attached to colon itself.

I *am*!!!


> If, as proposed elsewhere, we get rid of the %Foo:: notation in favor of
> some Foo<> variant, then trailing :: becomes available (ignoring ??/::
> for the moment), and
>
> new Dog:: tail => 'long'
>
> almost makes sense, insofar as it kinda looks like it's marking Dog
> as a type name, even though it isn't. But
>
> new Dog:: :tail<long>
>
> doesn't look so good.

Nor do object methods:

wag $dog:: 'tail';

say $fh:: $whatever;

> On the other hand, looking at it from the other end, the MMD notation
> tiebreaking notation is a little hard to spot, since colon is easy
> to miss.

Is it??? I've been writing quite a bit of MMD notation, and I think the colon
is very obvious...and exactly the right visual "weight".


> Maybe there's something that shows up better in a signature
> that also works as the invocant marker and, by extension, the indirect
> object marker. Since it's an ordering kind of thing, you'd kind of
> like to work > into it somehow, since the left side is of "greater"
> importance than the left. Unfortunately, though, "the good ones are
> all taken". Maybe some digraph like
>
> method new ($what*> $:tail) {...}
> method new ($what+> $:tail) {...}
> method new ($what.> $:tail) {...}
> method new ($what|> $:tail) {...}
> method new ($what>> $:tail) {...}
>
> giving
>
> new Dog*> :tail<long>
> new Dog+> :tail<long>
> new Dog.> :tail<long>
> new Dog|> :tail<long>
> new Dog>> :tail<long>
>
> I guess that last one is eqivalent to:
>
> method new ($what» $:tail) {...}
> new Dog» :tail<long>
>
> which I could maybe get used to. It kind of looks like a prompt to me.

Not one of these is anything close to as readable as:

new Dog: :tail<long>

name $dog: 'Rover';

say fh: @whatever

*Please* don't give up on the colon there. It's much more readable. I
especially like it for setting up objects:

$person = Contact.new;

first_name $person: "George";
family_name $person: "Bush";
title $person: "President";
email $person: "dap...@whitehouse.gov";
spouse $person: search $contacts: "Laura";


> The ordinary MMD might look like
>
> multi foo ($a, $b, $c» $d)
>
> And Lisp-like MMD fallback on every argument would look like
>
> multi foo ($a» $b» $c» $d»)
>
> I suppose that particular use of » could be construed as encouraging
> people not to do that. :-)

I truly believe that using the French quotes or (shudder!) their Texan
equivalents here would be a dire step backwards. They're already overloaded
for word lists and hyperoperators. I think using them for an invocant marker
as well would simply be too much.

The colon really was (and still is) the right choice here.

Damian

John Macdonald

unread,
Aug 24, 2005, 8:38:39 AM8/24/05
to Damian Conway, Larry Wall, Perl6 Language List
On Wed, Aug 24, 2005 at 04:27:03PM +1000, Damian Conway wrote:
> Larry wrote:
>
> >Plus I still think it's a really bad idea to allow intermixing of
> >positionals and named. We could allow named at the beginning or end
> >but still keep a constraint that all positionals must occur together
> >in one zone.
>
> If losing the magic from =>'d pairs isn't buying us named args wherever we
> like, why are we contemplating it?

When calling a function, I would like to be able to have a
mixture of named and positional arguments. The named argument
acts as a tab into the argument list and subsequent unnamed
arguments continue on. That allows you to use a name for a
group of arguments:

move( from=> $x, $y, delta=> $up, $right );

In this case, there could even be an optional z-coordinate
argument for each of the from and delta groups.

The named group concept works well for interfaces that use the
same groups in many different functions. It is especially
powerful in languages which do not have structured types,
which means it is not so necessary in Perl, but even here,
you often are computing the components (like $up and $right
above) separately, rather than always computing a single
structured value (which would mean writing delta=>(x=>$up,
y=>$right) instead).

--

Paul Seamons

unread,
Aug 24, 2005, 10:45:13 AM8/24/05
to perl6-l...@perl.org
I don't think this example reads very clearly. Visually you have to parse
until you see the next => and then back track one word to figure out the key.

> move( from=> $x, $y, delta=> $up, $right );

Personally I'd write that as either

move(from => [$x, $y], delta => [$up, $right]);

OR assuming I has a Position object and a vector object

move(from => $pos1, delta => $vec1);

The original example just seems difficult to parse.

Paul

John Williams

unread,
Aug 24, 2005, 12:11:24 PM8/24/05
to Damian Conway, Larry Wall, Perl6 Language List
On Wed, 24 Aug 2005, Damian Conway wrote:
> Larry wrote:
>
> > Plus I still think it's a really bad idea to allow intermixing of
> > positionals and named. We could allow named at the beginning or end
> > but still keep a constraint that all positionals must occur together
> > in one zone.
>
> If losing the magic from =>'d pairs isn't buying us named args wherever we
> like, why are we contemplating it?

I've lost track of the score in this thread, but I thought I would throw
a couple pennies into the fountain.

I really dread the thought of losing C< name => value > for named
parameters. Off the top of my head, ADA, PL/SQL, and php all use that
syntax, so it would be a shame to lose something that newbies might find
familiar.

On the other hand I would like it if the adverbial named parameter
style C< :name(value) > were allowed at the begining as well as the end of
the parameter list. I think adverbs read better when they are next to the
verbs they modify, and I would be nice if I didn't have to resort to macro
magic to get them there.

Mixing named and positionals is bad though.

~ John Williams


Chip Salzenberg

unread,
Aug 24, 2005, 1:12:39 PM8/24/05
to John Macdonald, Damian Conway, Larry Wall, Perl6 Language List
On Wed, Aug 24, 2005 at 08:38:39AM -0400, John Macdonald wrote:
> When calling a function, I would like to be able to have a
> mixture of named and positional arguments. The named argument
> acts as a tab into the argument list and subsequent unnamed
> arguments continue on.

I see a main point of named parameters to free the caller from the
tyranny of argument order (and vice versa). It seems to me you're
asking for the worst of both worlds.
--
Chip Salzenberg <ch...@pobox.com>

Dave Whipp

unread,
Aug 24, 2005, 2:32:50 PM8/24/05
to perl6-l...@perl.org
I've been trying to thing about how to make this read right without too
much line noise. I think Lukes keyword approach ("named") is on the
right track.

If we want named params at both start and end, then its bound to be a
bit confusing. But perhaps we can say that they're always at the end --
but either at the end of the invocant section or the end of the args.

Also, "named" is a bit of a clumsy name. "Where" and "given" are taken,
so I'll use "with":

I think something like these read nicely, without too much line noise:

draw_polygon $canvas: @verticies with color => "red";

draw_polygon $canvas with color => "red": @vertices;


Dave.

John Macdonald

unread,
Aug 24, 2005, 3:34:29 PM8/24/05
to Chip Salzenberg, John Macdonald, Damian Conway, Larry Wall, Perl6 Language List

Perhaps I didn't make it clear in my original message -
I agree that arbitrary mixing of named and positional is
usually a bad thing.

The only place where I find it useful is with a group of
arguments that are always provided in the same order, used one
or more times each by a number of functions, with additional
arguments for some/all of those functions.

So, a function that takes position and/or vector values would
provide a name for each vector/position, but expect each to have
an x, a y, and (possibly) a z argument following the name.

I saw this in the DO system - a shell written at CDC back in
the late 70's. The provided scripts were designed so that
all programming scripts used the same sequence of arguments
after the OPT keyword, the LINK keywork, etc.

As I said originally, the value is diluted in a language
with structured data types - you can use a single argument
for a position that is a hash or array which contains the
x/y/z components within it.

The named group helps especially if you generally want to
provide separate-but-related arguments. This tends to be
things like an optional sub-action that requires multiple
parameters if it is used at all.

So, I'm mostly saying that a mixture of named and positional
arguments is not ALWAYS bad, and that there may be some
value in permitting such a mixture in certain circumstances.

--

Luke Palmer

unread,
Aug 25, 2005, 5:23:42 AM8/25/05
to Damian Conway, Larry Wall, Perl6 Language List
On 8/24/05, Damian Conway <dam...@conway.org> wrote:
> Larry wrote:
>
> > Plus I still think it's a really bad idea to allow intermixing of
> > positionals and named. We could allow named at the beginning or end
> > but still keep a constraint that all positionals must occur together
> > in one zone.
>
> If losing the magic from =>'d pairs isn't buying us named args wherever we
> like, why are we contemplating it?

Well, that was one of the nice side-effects of the proposal, solving
something that had been bugging me. But the main reason for this
proposal was to demote Pair into a regular data type that wouldn't
sneak into somebody's named argument when we weren't looking. In the
Old Regime, I fear that I would never ever use Pair *except* for named
arguments precisely because I need to keep far too much information in
my head to use them safely.

> > so we should put some thought into making it syntactically trivial, if
> > not automatic like it is now.

The whole point was to deautomatize it! However, here's an
interesting solution: pairs are scanned for *syntactically* *on the
top level* of a function call (allowing named() or however we spell it
as a fallback when we want to be dynamic). However, :foo(bar) and foo
=> bar are equivalent again.

foo $x, $y; # two positionals, regardless of what they contain
foo $x, :y($y) # a positional and a named
foo $x, y => $y # a positional and a named
foo $x, (y => $y) # two positionals: $x and the pair y => $y
foo $x, (:y($y)) # same

In the fourth example, y => $y is no longer on the syntactic top
level, so it is not interpreted as a named argument.


>
> > I hate to say it, but the named args should probably be marked
> > with : instead of + in the signature.

That's pretty cool. Can't say I like the secondary sigil: it's really
not marking a property of the variable, but a property of the
parameter list. That information should probably be kept inside the
parameter list alone.

Luke

Stuart Cook

unread,
Aug 25, 2005, 6:23:55 AM8/25/05
to Perl6 Language List
Here's a suggestion:

Outside of argument lists, both a=>'b' and :a('b') (and friends) are
equivalent, and denote an ordinary pair value.

Within argument lists, both of them are special syntactic forms for
named arguments:

foo(a => 'b', :c<d>); # both named args

If you want to pass pair values into a sub, either use an intermediate
variable...

my $pair = :a<b>;
foo($pair); # not a named-arg call

...or else find new syntax to disambiguate:

foo( (a => 'b') ); # ok, so maybe parens aren't such a good idea

Or just use existing language constructs:

foo( do{a=>'b'}, {:c<d>;}() ); # both positional args

And if you explicitly want to use individual pair values as named
args, just exploit the fact that a pair can act like a one-element
hash, and splat it:

my $arg = :echo<foxtrot>;
foo( *%$arg ); # yes, I know it's three symbols

Then the only magic rule most people need to remember is:

"Pair syntax denotes named-arg passing, but only in an arg list."

Magic can never be hidden (or happen accidentally), people can
explicitly circumvent the default behaviour, and the whole system has
very little inconsistency.

Thoughts?


Stuart

Yuval Kogman

unread,
Aug 25, 2005, 6:49:10 AM8/25/05
to Stuart Cook, Perl6 Language List
On Thu, Aug 25, 2005 at 20:23:55 +1000, Stuart Cook wrote:
> Here's a suggestion:
<snip>

> Within argument lists, both of them are special syntactic forms for
> named arguments:
>
> foo(a => 'b', :c<d>); # both named args
<snip>

> my $pair = :a<b>;
> foo($pair); # not a named-arg call
<snip>

> ...or else find new syntax to disambiguate:

For disambiguation I think we should have symmetric functions:

foo(pairs(a => 'b', :c<d>));



my $pair = :a<b>;

foo(named($pair));

This can be implemented in a number of ways (NamedArg isa Pair,
macros, special construct).

Edge case:

foo(my $x = :foo<bah>);
bar($x);

As I see it in this example bar is getting a pair, not a named
argument.

foo() on the other hand could get either a named argument since
:foo<bah> was in it's parameters, or a pair, since (my $x =
:foo<bah>) is an expression.

If the named semantics are in the micro-lexical scope of the call to
the pair constructor, foo() gets a named. If not, it gets a pair.

In either condition, there should be a warning:

"Possible unintended use of pair instead of named argument in
:foo<bah>, call to foo() at ..."

and disambiguation can fix this:

foo(named(my $x = :foo<bah>));
foo(pair(my $x = :foo<bah>));

--
() Yuval Kogman <nothi...@woobling.org> 0xEBD27418 perl hacker &

/\ kung foo master: /me groks YAML like the grasshopper: neeyah!!!!!!

TSa

unread,
Sep 20, 2005, 12:04:01 PM9/20/05
to Perl6 Language List
HaloO,

Luke Palmer wrote:
> The whole point was to deautomatize it! However, here's an
> interesting solution: pairs are scanned for *syntactically* *on the
> top level* of a function call (allowing named() or however we spell it
> as a fallback when we want to be dynamic). However, :foo(bar) and foo
> => bar are equivalent again.
>
> foo $x, $y; # two positionals, regardless of what they contain
> foo $x, :y($y) # a positional and a named
> foo $x, y => $y # a positional and a named
> foo $x, (y => $y) # two positionals: $x and the pair y => $y
> foo $x, (:y($y)) # same
>
> In the fourth example, y => $y is no longer on the syntactic top
> level, so it is not interpreted as a named argument.

Isn't that a task for the itemizer? I mean

foo $x, [y => $y] # syntactic arg type = (Item,Item)
# but static arg type = (Item,Pair)
foo $x, [:y($y)] # same

compared to

foo $x, y => $y # syntactic arg type = (Item,Pair)
# and static arg type = (Item,Pair)
foo $x, (y => $y) # same because () only groups for changed precedence


>>>I hate to say it, but the named args should probably be marked
>>>with : instead of + in the signature.
>
>
> That's pretty cool. Can't say I like the secondary sigil: it's really
> not marking a property of the variable, but a property of the
> parameter list. That information should probably be kept inside the
> parameter list alone.

I have changed my mind on $.foo and $:foo because these forms just lack
some identifyer chars between the two sigils $what.foo and $what:foo where
now $what indicates an item and .foo a method on it. Well, and :foo
indicates a keyed access on $what, but that isn't currently specced, right?
So what does 'what' default to in $.foo and $:foo? I think it simply is
'?SELF' and the twigil syntax gives a compile error if $?SELF is unbound.

The other two twigil combinations .$foo and :$foo in that logic would be
a method ref and a key ref respectively and as such both need something
on their left side. If that happens to be a bare word as in

blahh :$foo;

my interpretation is that first of all the symbol lookup for blahh has to
yield a sub. Since it's not sigiled &blahh it is a not yet invoked sub
invocation---to me this is not weirder than an unthrown exception---and
$foo has to contain a pair that is bound by name in the pending blahh
invocation. In other words it's a parametric, named parameter. BTW, if
you want the same through a sub call I would write it as

blahh :&foo();

See also my 'syntactic, static and dynamic type' mail. The forms

blahh .$foo;
blahh .&foo();

require blahh to be callable without params and return a suitable
invocant type for the method referenced by $foo and returned by
calling the sub foo respectively. This (il)logic can be applied
to other twigil combinations as well:

blahh .@foo[42]; # call on blahh ret val through method ref from @foo[42]
blahh :%foo<some_pair> # call blahh with named param from %foo<some_pair>

All of these forms fail at runtime if e.g. @foo[42] doesn't yield a method
ref and even if it does the dispatch on the retval of blahh might fail. The
compiler could also warn or give errors if the invocations can be proven
to fail from the static type information, e.g.

my Int @foo;

blahh .@foo[42]; # Int not a Method subtype


Hmm, and if you mentally unify sub and class you get the idea that
$?SELF is bound to the current invocation err instance of the sub
and as such is amenable to the $:foo syntax for replacing placeholder
variables. That means

{ $:y < $:z && $:x != 2 }

is a shorthand for

sub ($x,$y,$z) { $y < $z && $x != 2 }

and hints at the possibility for writing sub definitions as

sub foo:(Item,Item,Item --> bool)
{
has $x; # first,
has $y; # second,
has $z; # and third Item

has $:trace;

if defined $:trace { say $:trace }

return $y < $z && $x != 2;
}

and call them as usual

foo 1,2,3; # no trace

foo 1,2,3, trace => 'should be false';

foo:trace<should be false> 1,2,3; # same

foo 1,2,3, :trace($count++);

foo 1,2,3, :$count++; # works?

and curry them with slot assignment

my &foo ::= &OUTER::foo:trace<foo called>;

foo 1,2,3; # prints traces
--
$TSa.greeting := "HaloO"; # mind the echo!

Reply all
Reply to author
Forward
0 new messages