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

Sane (less insane) pair semantics

1 view
Skip to first unread message

Ingo Blechschmidt

unread,
Oct 9, 2005, 2:22:59 PM10/9/05
to perl6-l...@perl.org
Hi,

while fixing bugs for the imminent Pugs 6.2.10 release, we ran into
several issues with magical pairs (pairs which unexpectedly participate
in named binding) again. Based on Luke's "Demagicalizing pairs" thread
[1], #perl6 refined the exact semantics [2].

The proposed changes are:

* "(key => $value)" (with the parens) is always a positionally passed
Pair object. "key => $value" (without the parens) is a named
parameter:

sub foo ($a) {...}

foo(a => 42); # named parameter "a", $a will be 42
foo(:a(42)); # same

foo((a => 42)); # positional parameter (a pair),
# $a will be the Pair (a => 42)
foo((:a(42))); # same

* Passing a variable containing a Pair is always passed positionally:

my $pair = (a => 42); # or :a(42)

foo($pair); # positional parameter, $a will be the Pair (a => 42)

* Unary "*" makes a normal pair variable participate in named binding:

foo(*$pair); # named parameter "a", $a will be 42

* Same for hashes:

my %hash = (a => 1, b => 2, c => 3);

foo(%hash); # positional parameter, $a will be \%hash

foo(*%hash); # three named parameters

Opinions?


--Ingo

[1] http://article.gmane.org/gmane.comp.lang.perl.perl6.language/4778/
[2]
http://colabti.de/irclogger/irclogger_log/perl6?date=2005-10-09,Sun&sel=528#l830

Uri Guttman

unread,
Oct 9, 2005, 3:08:56 PM10/9/05
to Ingo Blechschmidt, perl6-l...@perl.org
>>>>> "IB" == Ingo Blechschmidt <ibl...@web.de> writes:


IB> * "(key => $value)" (with the parens) is always a positionally passed
IB> Pair object. "key => $value" (without the parens) is a named
IB> parameter:

IB> sub foo ($a) {...}

IB> * Unary "*" makes a normal pair variable participate in named binding:

IB> foo(*$pair); # named parameter "a", $a will be 42

IB> * Same for hashes:

IB> my %hash = (a => 1, b => 2, c => 3);

IB> foo(%hash); # positional parameter, $a will be \%hash

IB> foo(*%hash); # three named parameters

IB> Opinions?

works for me. but what about lists and arrays?

my @z = ( 'a', 1 ) ;
foo( @z ) # $a = [ 'a', 1 ] ??

my @z = ( a => 1 ) ;
foo( @z ) # $a = pair( a => 1 ) or does that need * too?

same questions for lists (this shows a nested sub call)

sub bar { return ( a => 1 ) }
foo( bar() ) # i would expect $a == ( a => 1 ) since there is
# no *

foo( *bar() ) # i would expect $a == 1

i think i covered most/all of the variations. but this needs to be
hammered down for all of them.

thanx,

uri

--
Uri Guttman ------ u...@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Ingo Blechschmidt

unread,
Oct 9, 2005, 3:19:51 PM10/9/05
to perl6-l...@perl.org
Hi,

Uri Guttman wrote:
>>>>>> "IB" == Ingo Blechschmidt <ibl...@web.de> writes:
> IB> * "(key => $value)" (with the parens) is always a positionally
> passed
> IB> Pair object. "key => $value" (without the parens) is a named
> IB> parameter:
>
> IB> sub foo ($a) {...}
>
> IB> * Unary "*" makes a normal pair variable participate in named
> binding:
>
> IB> foo(*$pair); # named parameter "a", $a will be 42
>
> IB> * Same for hashes:
>
> IB> my %hash = (a => 1, b => 2, c => 3);
>
> IB> foo(%hash); # positional parameter, $a will be \%hash
>
> IB> foo(*%hash); # three named parameters
>
> IB> Opinions?
>
> works for me.

Great! :)

> but what about lists and arrays?
>
> my @z = ( 'a', 1 ) ;
> foo( @z ) # $a = [ 'a', 1 ] ??

Yep.

> my @z = ( a => 1 ) ;
> foo( @z ) # $a = pair( a => 1 ) or does that need * too?

No. Even foo(*@z) would cause $a to be the Pair (a => 1).
If you really wanted to have an array of pairs participate in named
binding, you'd have to write:

foo(*hash(@z)); # (which is short for)
my %hash = @z; foo(*%hash);

> same questions for lists (this shows a nested sub call)
>
> sub bar { return ( a => 1 ) }
> foo( bar() ) # i would expect $a == ( a => 1 ) since there is
> # no *

Yep.

> foo( *bar() ) # i would expect $a == 1

Yep.


--Ingo

Yuval Kogman

unread,
Oct 9, 2005, 3:36:37 PM10/9/05
to Ingo Blechschmidt, perl6-l...@perl.org
On Sun, Oct 09, 2005 at 20:22:59 +0200, Ingo Blechschmidt wrote:
> Opinions?

Yes!

--
() Yuval Kogman <nothi...@woobling.org> 0xEBD27418 perl hacker &
/\ kung foo master: *shu*rik*en*sh*u*rik*en*s*hur*i*ke*n*: neeyah!!!!

Luke Palmer

unread,
Oct 9, 2005, 5:42:46 PM10/9/05
to Uri Guttman, Ingo Blechschmidt, perl6-l...@perl.org
On 10/9/05, Uri Guttman <u...@stemsystems.com> wrote:
> >>>>> "IB" == Ingo Blechschmidt <ibl...@web.de> writes:
> IB> sub foo ($a) {...}

>
> works for me. but what about lists and arrays?
>
> my @z = ( 'a', 1 ) ;
> foo( @z ) # $a = [ 'a', 1 ] ??

Yep.

> my @z = ( a => 1 ) ;
> foo( @z ) # $a = pair( a => 1 ) or does that need * too?

$a = [ a => 1 ]

You passed an array. The parameter gets an array.

> same questions for lists (this shows a nested sub call)
>
> sub bar { return ( a => 1 ) }
> foo( bar() ) # i would expect $a == ( a => 1 ) since there is
> # no *
>
> foo( *bar() ) # i would expect $a == 1

Yeah, I think your expectations are correct.

Basically, * takes whatever kind of object it is (array, hash, pair)
and pretends that you wrote its contents literally into the argument
list.

Luke

Uri Guttman

unread,
Oct 9, 2005, 5:52:00 PM10/9/05
to Luke Palmer, Ingo Blechschmidt, perl6-l...@perl.org
>>>>> "LP" == Luke Palmer <lrpa...@gmail.com> writes:

LP> On 10/9/05, Uri Guttman <u...@stemsystems.com> wrote:
>> >>>>> "IB" == Ingo Blechschmidt <ibl...@web.de> writes:
IB> sub foo ($a) {...}
>>
>> works for me. but what about lists and arrays?
>>
>> my @z = ( 'a', 1 ) ;
>> foo( @z ) # $a = [ 'a', 1 ] ??

LP> Yep.

>> my @z = ( a => 1 ) ;
>> foo( @z ) # $a = pair( a => 1 ) or does that need * too?

LP> $a = [ a => 1 ]

LP> You passed an array. The parameter gets an array.

right. and it has one pair inside.

>> same questions for lists (this shows a nested sub call)
>>
>> sub bar { return ( a => 1 ) }
>> foo( bar() ) # i would expect $a == ( a => 1 ) since there is
>> # no *
>>
>> foo( *bar() ) # i would expect $a == 1

LP> Yeah, I think your expectations are correct.

LP> Basically, * takes whatever kind of object it is (array, hash, pair)
LP> and pretends that you wrote its contents literally into the argument
LP> list.

that is a succinct statement of how * work but you also have to describe
the cases with pairs and such and no *. and what about the case that
ingo said needed *hash()? i think a list of all the know variations (*
and no *) should be done to keep the behavior clear to all. just more of
the examples we have so far and what gets set in the args for each. it
will also make it easier to create tests for these and to get this into
pugs.

Stuart Cook

unread,
Oct 9, 2005, 7:27:41 PM10/9/05
to perl6-l...@perl.org
The think I don't like about `foo( *$bar )` is that it's not clear
whether you're splatting a pair, or a hash, or an array, or a complete
argument-list object. This is probably fine for quick-'n'-dirty code,
but I'd like to encourage a more explicit style:

my %hash = (a=>'b', c=>'d');
foo( *%hash ); # splat a hash as named arguments
# => foo( a=>'b', c=>'d' );

my $pair = a=>'b';
foo( *%$pair ); # view the pair as a 1-elem hash, and splat that

my $href = \%hash; # or just %hash
foo( *%$href ); # view the hashref as a hash, and splat that

sub returns_a_hash { ... }
foo( *%{returns_a_hash} ); # call the sub, view the result as a
hash, and splat that

my @array = (1, 2, 3);
foo( *@array ); # splat an array as positional arguments
# => foo( 1, 2, 3 );

my $aref = \@array; # or just @array
foo( *@$aref ); # view the arrayref as an array, and splat that

sub returns_an_array { ... }
foo( *@{returns_an_array} ); # call the sub, view the result as a
hash, and splat that

In this style, the splat character (*) is always next to a sigil (% or
@) telling you exactly how the arguments are being substituted (named
or positional).

I'm also a little wary of giving parens the power to change pair
behaviour, but the rules are simple enough that I can probably get
over it. The other proposal, IIRC, was to have `named()` and `pair()`
special-forms for forcing the desired behaviour; these would only be
valid in argument lists.


Stuart

Austin Hastings

unread,
Oct 9, 2005, 8:20:19 PM10/9/05
to Ingo Blechschmidt, perl6-l...@perl.org
Ingo Blechschmidt wrote:

>Hi,
>
>while fixing bugs for the imminent Pugs 6.2.10 release, we ran into
>several issues with magical pairs (pairs which unexpectedly participate
>in named binding) again. Based on Luke's "Demagicalizing pairs" thread
>[1], #perl6 refined the exact semantics [2].
>
>The proposed changes are:
>
>* "(key => $value)" (with the parens) is always a positionally passed
> Pair object. "key => $value" (without the parens) is a named
> parameter:
>
> sub foo ($a) {...}
>
> foo(a => 42); # named parameter "a", $a will be 42
> foo(:a(42)); # same
>
>
>
> foo((a => 42)); # positional parameter (a pair),
> # $a will be the Pair (a => 42)
> foo((:a(42))); # same
>
>
>

What about whitespace?

foo (a => 42); # Note space

Is that the first case (subcall with named arg) or the second case (sub
with positional pair)?

>* Passing a variable containing a Pair is always passed positionally:
>
> my $pair = (a => 42); # or :a(42)
>
> foo($pair); # positional parameter, $a will be the Pair (a => 42)
>
>* Unary "*" makes a normal pair variable participate in named binding:
>
> foo(*$pair); # named parameter "a", $a will be 42
>
>* Same for hashes:
>
> my %hash = (a => 1, b => 2, c => 3);
>
> foo(%hash); # positional parameter, $a will be \%hash
>
> foo(*%hash); # three named parameters
>
>Opinions?
>
>
>--Ingo
>
>[1] http://article.gmane.org/gmane.comp.lang.perl.perl6.language/4778/
>[2]
>http://colabti.de/irclogger/irclogger_log/perl6?date=2005-10-09,Sun&sel=528#l830
>
>
>

What's the most complete way to get the sub's arguments?

That is, for a sub that takes positional, optional, named, and variadic
(*) arguments, what's the best mechanism for grabbing the entire call?

Your reply to Uri:

> Uri Guttman wrote:

>> but what about lists and arrays?
>>
>> my @z = ( 'a', 1 ) ;
>> foo( @z ) # $a = [ 'a', 1 ] ??
>
>

> Yep.

Suggests that I cannot pass along parameters in the usual way:

sub foo(...)
{
bar(@_);
}

Does that work if I code it as

bar @_;

(which is huffmanly, but hardly intuitive).

=Austin

Stuart Cook

unread,
Oct 9, 2005, 10:30:37 PM10/9/05
to perl6-l...@perl.org
On 10/10/05, Austin Hastings <Austin_...@yahoo.com> wrote:
> What about whitespace?
>
> foo (a => 42); # Note space
>
> Is that the first case (subcall with named arg) or the second case (sub
> with positional pair)?

Sub with positional pair, since the parens aren't call-parens (because
of the space), so they protect the pair. It would probably be prudent
to emit a warning in this case, for obvious reasons. (Actually, this
is one of the major problems with using parens to protect pair args.)

> What's the most complete way to get the sub's arguments?
>
> That is, for a sub that takes positional, optional, named, and variadic
> (*) arguments, what's the best mechanism for grabbing the entire call?

As far as I know there currently *isn't* a concise way to
capture/forward all (or some) of a sub's arguments; the closest thing
is:

sub foo(*@pos, *%named) { bar(*@pos, *%named) }

Which is ugly and unwieldy. I believe Luke was considering some kind
of 'unified arg-list object' which you could use to slurp and splat
entire argument lists, like so:

sub foo(*$args) { bar(*$args) }

But I don't think it's been posted to the list yet.


Stuart

Uri Guttman

unread,
Oct 9, 2005, 11:17:06 PM10/9/05
to Stuart Cook, perl6-l...@perl.org
>>>>> "SC" == Stuart Cook <sco...@gmail.com> writes:

SC> The think I don't like about `foo( *$bar )` is that it's not clear
SC> whether you're splatting a pair, or a hash, or an array, or a complete
SC> argument-list object. This is probably fine for quick-'n'-dirty code,
SC> but I'd like to encourage a more explicit style:

but perl will know the type of the value in $bar and expand/splat it
accordingly.


SC> my $pair = a=>'b';
SC> foo( *%$pair ); # view the pair as a 1-elem hash, and splat that

the % there isn't a hash. perl can see the single pair and deal with
that. the way to make this more readable is to use better variable
names. $pair here is fine and *$pair would mean to splat it into the
named arguments.

SC> my $href = \%hash; # or just %hash
SC> foo( *%$href ); # view the hashref as a hash, and splat that

same as above. perl sees the href and will just DWIM.

SC> sub returns_a_hash { ... }
SC> foo( *%{returns_a_hash} ); # call the sub, view the result as a
SC> hash, and splat that

isn't that what hash() is for? what is returns_a_hash really returning,
a list or a hash ref because you can't return a hash (or can you this
week? :).

SC> my $aref = \@array; # or just @array
SC> foo( *@$aref ); # view the arrayref as an array, and splat that

again, autoderef would work fine here. i don't see the benefit of the
extra @.

SC> sub returns_an_array { ... }
SC> foo( *@{returns_an_array} ); # call the sub, view the result as a
SC> hash, and splat that

where is the hash? wouldn't you want %{} in your system? and %{} derefs
a hash and doesn't convert a list to a hash. that is what hash() does.

Austin Hastings

unread,
Oct 10, 2005, 1:25:23 AM10/10/05
to perl6-l...@perl.org
Stuart Cook wrote:

>On 10/10/05, Austin Hastings <Austin_...@yahoo.com> wrote:
>
>
>>What about whitespace?
>>
>> foo (a => 42); # Note space
>>
>>Is that the first case (subcall with named arg) or the second case (sub
>>with positional pair)?
>>
>>
>
>Sub with positional pair, since the parens aren't call-parens (because
>of the space), so they protect the pair. It would probably be prudent
>to emit a warning in this case, for obvious reasons. (Actually, this
>is one of the major problems with using parens to protect pair args.)
>
>
>

So to pass a hash that has one element requires using the <c>hash</c>
keyword?

Specifically, if I say:

@args = (a => 1, get_overrides());

Then can I say

foo(*@args);

Or will I, in the case of no overrides, get a positional pair instead of
named a =>1 ?


>>What's the most complete way to get the sub's arguments?
>>
>>That is, for a sub that takes positional, optional, named, and variadic
>>(*) arguments, what's the best mechanism for grabbing the entire call?
>>
>>
>
>As far as I know there currently *isn't* a concise way to
>capture/forward all (or some) of a sub's arguments; the closest thing
>is:
>
> sub foo(*@pos, *%named) { bar(*@pos, *%named) }
>
>Which is ugly and unwieldy. I believe Luke was considering some kind
>of 'unified arg-list object' which you could use to slurp and splat
>entire argument lists, like so:
>
> sub foo(*$args) { bar(*$args) }
>
>But I don't think it's been posted to the list yet.
>
>
>

It seems like positionals, if specified, should appear as pairs in
*@whatever
unless a hash is also present. That is, @_ or its replacement as the
collection-of-all-arguments-given should be a list, for positionalness,
and should include pairs when necessary.

=Austin

Stuart Cook

unread,
Oct 10, 2005, 2:28:56 AM10/10/05
to perl6-l...@perl.org
(It seems you're confused about my position because I was sloppy
presenting it. My apologies; hopefully this will clear a few things
up.)

On 10/10/05, Uri Guttman <u...@stemsystems.com> wrote:


> Stuart Cook <sco...@gmail.com> writes:
>
> > The think I don't like about `foo( *$bar )` is that it's not clear

> > whether you're splatting a pair, or a hash, or an array, or a complete

> > argument-list object. This is probably fine for quick-'n'-dirty code,

> > but I'd like to encourage a more explicit style:
>
> but perl will know the type of the value in $bar and expand/splat it
> accordingly.

I realise that perl can cope with it--my concern was more for the
person reading the code. Just like perl can cope without explicit
type annotations, but some of us will choose to write them anyway.

The idea is that when you (the human) see *%, you _know_ it's a named
splat, and when you see *@ you _know_ it's a positional splat. With
*$, it could be either, depending on what's in the variable. I agree
that sensible variable names and type annotations should make this a
minor issue, it's just that I'd sometimes like to add an extra sigil
for additional clarity.

And to clarify, as far as I'm aware, nothing I suggested here is new
syntax--just ways of combining existing explicit-deref syntax with (*)
to produce more self-descriptive code.

> > my $pair = a=>'b';

> > foo( *%$pair ); # view the pair as a 1-elem hash, and splat that
>
> the % there isn't a hash. perl can see the single pair and deal with
> that. the way to make this more readable is to use better variable
> names. $pair here is fine and *$pair would mean to splat it into the
> named arguments.

My understanding (possibly incorrect) was that the % 'derefs' the pair
into a one-element hash, in much the same way that %$href derefs a
hashref into a hash. From there, *%$pair is exactly the same as:

# there's probabaly a shorter way of writing this first line, but
I'm shooting for clarity :)
my %hash = ($pair.key => $pair.value);
foo( *%hash );

> > sub returns_a_hash { ... }


> > foo( *%{returns_a_hash} ); # call the sub, view the result as a

> > hash, and splat that
>
> isn't that what hash() is for? what is returns_a_hash really returning,
> a list or a hash ref because you can't return a hash (or can you this
> week? :).

My sloppy language again--the idea was that &returns_a_hash produces a
hashref, which is dereffed by %{}, and finally splatted.

> > sub returns_an_array { ... }


> > foo( *@{returns_an_array} ); # call the sub, view the result as a

> > hash, and splat that
>
> where is the hash? wouldn't you want %{} in your system? and %{} derefs
> a hash and doesn't convert a list to a hash. that is what hash() does.

Sorry, that was meant to say "view the result as an array". (I swear
I proofread that post!)

In summary:
1) I believe all my suggestions use currently-existing syntax (modulo
errors on my part)
2) Yes, the extra sigils/derefs are redundant, but sometimes we want
to be explicit
3) I don't particularly object to `foo( *$pair )` also working; this
is meant as an extra option


Stuart

Stuart Cook

unread,
Oct 10, 2005, 7:58:43 AM10/10/05
to perl6-l...@perl.org
On 10/10/05, Austin Hastings <Austin_...@yahoo.com> wrote:
> So to pass a hash that has one element requires using the <c>hash</c>
> keyword?

I don't see a hash in your example, so I'm not sure what you're
referring to here.

> Specifically, if I say:
>
> @args = (a => 1, get_overrides());
>
> Then can I say
>
> foo(*@args);

Not if you want that a=>1 to be a named argument.

Under the proposal, the only ways to pass a named argument are:
1) By using a literal pair in the syntactic top-level of the arg list
2) By splatting a pair, hash, or arg-list-object

> Or will I, in the case of no overrides, get a positional pair instead of
> named a =>1 ?

The overrides have nothing to do with it. That a=>1 will *always* be
a positional, because by the time it reaches the argument list, it's a
value (not a syntactic form). The only way to use a pair-value as a
named argument is to splat it directly, or splat a hash or
arg-list-object containing it. Splatting an array *never* introduces
named arguments, only positionals.


Stuart

Juerd

unread,
Oct 10, 2005, 8:59:19 AM10/10/05
to perl6-l...@perl.org
Stuart Cook skribis 2005-10-10 22:58 (+1100):

> > @args = (a => 1, get_overrides());
> > foo(*@args);
> Not if you want that a=>1 to be a named argument.
> Under the proposal, the only ways to pass a named argument are:
> 1) By using a literal pair in the syntactic top-level of the arg list
> 2) By splatting a pair, hash, or arg-list-object

I find this counterintuitive, and also want arrays to be included in
option 2.

It is consistent with the idea that * expands its RHS and evaluate it as
if it was written literally.

I'd like @_ or @?ARGS or something like that to be a *-able array that
will be guaranteed to be compatible with the current sub's signature.


Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html

Juerd

unread,
Oct 10, 2005, 9:20:51 AM10/10/05
to perl6-l...@perl.org
Miroslav Silovic skribis 2005-10-10 15:04 (+0200):

> >>Under the proposal, the only ways to pass a named argument are:
> >>1) By using a literal pair in the syntactic top-level of the arg list
> >>2) By splatting a pair, hash, or arg-list-object
> >I find this counterintuitive, and also want arrays to be included in
> How would you splat an array of pairs if you want to preserve the pairs?

By adding parens, because by this proposal (if I read it correctly),
only pairs on the topmost level of arguments (not in any parens) are
parsed as named arguments.

foo((*@array));
foo (*@array);

This doesn't allow for combining named and positional pairs. I do not
think that is necessary at all, for arrays. I think that combining
the two on the same level is a recipe for disaster anyway, and should
perhaps even emit a warning.

Juerd

unread,
Oct 10, 2005, 9:23:14 AM10/10/05
to perl6-l...@perl.org
Juerd skribis 2005-10-10 15:20 (+0200):

> only pairs on the topmost level of arguments (not in any parens) are

s/not in any parens/not in any grouping parens/, to exclude .()

Miroslav Silovic

unread,
Oct 10, 2005, 9:04:29 AM10/10/05
to ju...@convolution.nl, perl6-l...@perl.org
ju...@convolution.nl wrote:

>Stuart Cook skribis 2005-10-10 22:58 (+1100):
>
>
>>> @args = (a => 1, get_overrides());
>>> foo(*@args);
>>>
>>>
>>Not if you want that a=>1 to be a named argument.
>>Under the proposal, the only ways to pass a named argument are:
>>1) By using a literal pair in the syntactic top-level of the arg list
>>2) By splatting a pair, hash, or arg-list-object
>>
>>
>
>I find this counterintuitive, and also want arrays to be included in
>option 2.
>
>

How would you splat an array of pairs if you want to preserve the pairs?

>It is consistent with the idea that * expands its RHS and evaluate it as


>if it was written literally.
>
>I'd like @_ or @?ARGS or something like that to be a *-able array that
>will be guaranteed to be compatible with the current sub's signature.
>
>
>

This sounds nice, though. Maybe it suggests that the 'named splat'
should be something other than *?

Miro


Larry Wall

unread,
Oct 10, 2005, 10:46:36 AM10/10/05
to perl6-l...@perl.org
Interestingly, I had already written almost exactly the same thing
into my version of S06, but I've been holding off on checking it in
while I mull over Luke's theory theory. Regardless of the actual
syntax we end up with, I think everyone can assume that the compiler
will be able to determine at compile time which pairs are intended
to be named arguments and which ones positional parameters, and pass
them as separate entities through whatever structure supplies all the
arguments to a call so that the caller doesn't have to worry about
making the distinction based on type.

It still has to figure out how to reconcile the named arguments
with the positional parameters, of course, unless someone has
made sufficient representation to the compiler that all calls to
a particular short name have particular named parameters that are
guaranteed to be in the same position everywhere, in which case the
compiler is allowed to simply translate them to positionals on the
call end.

Perhaps it would be useful to allow a stubbed multi to declare the
required names of positional parameters in some scope or other. This
might be generalized to a translation service for calls outside the
scope, where the current scope could even be the current language
as a whole. That might alleviate cultural differences if one language
always uses $left and $right where another uses x and y, for instance.

Of course, I haven't eaten breakfast yet, so maybe that's impossible.

Larry

Austin Hastings

unread,
Oct 10, 2005, 9:39:52 AM10/10/05
to p6l
Stuart Cook wrote:

>On 10/10/05, Austin Hastings <Austin_...@yahoo.com> wrote:
>
>
>The overrides have nothing to do with it. That a=>1 will *always* be a positional, because by the time it reaches the argument list, it's a value (not a syntactic form). The only way to use a pair-value as a named argument is to splat it directly, or splat a hash or arg-list-object containing it. Splatting an array *never* introduces named arguments, only positionals.
>
>

That seems like a huge error. Arrays are the only thing (that I know of)
that can store the positional part of an arglist as well as storing the
pairs. If there's not some mechanism for getting the entire arglist, and
if there's not some simple inversion of that simple mechanism for
passing the args along to some other victim, then ... well ... I don't
know. But it's bad!

So since you keep saying "arg-list-object" as though it was something
not an array, I'll bite:

What's an arg-list-object, and how is it different from an array?


=Austin


Austin Hastings

unread,
Oct 10, 2005, 11:15:05 AM10/10/05
to perl6-l...@perl.org
Miroslav Silovic wrote:

> ju...@convolution.nl wrote:
>
>> * expands its RHS and evaluate it as if it was written literally.
>>
>> I'd like @_ or @?ARGS or something like that to be a *-able array that
>> will be guaranteed to be compatible with the current sub's signature.
>>
> This sounds nice, though. Maybe it suggests that the 'named splat'
> should be something other than *?


How about "perl should DWIM"? In this case, I'm with Juerd: splat should
pretend that my array is a series of args.

So if I say:

foo *@args;

or if I say:

foo(*@args);

I still mean the same thing: shuck the array and get those args out
here, even the pairs.

It's worth pointing out that perl does know the list of declared named
args, though that may not be enough. If the pair.key matches an expected
arg, then splat should collapse it for sure. If it doesn't match...I dunno.

Is there a list() operator for converting hashes into lists of pairs?
That might make parsing foo(*@_, *%_) more palatable, but I'd still
prefer to get pairs in @_ if I don't explicitly ask for *%_...

=Austin

Ingo Blechschmidt

unread,
Oct 10, 2005, 1:36:03 PM10/10/05
to perl6-l...@perl.org
Hi,

Austin Hastings wrote:
> How about "perl should DWIM"? In this case, I'm with Juerd: splat
> should pretend that my array is a series of args.

Yep.

> So if I say:
>
> foo *@args;
>
> or if I say:
>
> foo(*@args);
>
> I still mean the same thing: shuck the array and get those args out
> here, even the pairs.

Right, you name it: you get *pairs* out of the array, not named
parameters. Under the proposal, a Pair object doesn't have any special
magic -- it's simply

class Pair { has $.key; has $.value is rw }

Thus:

my @array = (42, "hi", (a => 23));
foo *@array; # same as

foo 42, "hi", (a => 23); # three positional params (Int, Str, Pair)

> It's worth pointing out that perl does know the list of declared named
> args, though that may not be enough. If the pair.key matches an
> expected arg, then splat should collapse it for sure. If it doesn't
> match...I dunno.

But that's exactly the problem. You shouldn't have to worry about any
special magic when dealing with *@array. Consider:

sub foo ($a, $b, $c, ?$d) {...}

my @array = (1, 2, (key => "value"));
foo *@array; # fine, no problem, $c will receive (key => "value")

my @array = (1, 2, (d => "value"));
foo *@array; # oops! $a = 1, $d = "value"
# "Required argument 'c' not given!"

> Is there a list() operator for converting hashes into lists of pairs?

my @array_of_pairs = %hash; # short for
my @array_of_pairs = list %hash;


--Ingo

Dave Whipp

unread,
Oct 10, 2005, 1:48:26 PM10/10/05
to perl6-l...@perl.org
Austin Hastings wrote:

> How about "perl should DWIM"? In this case, I'm with Juerd: splat should
> pretend that my array is a series of args.
>
> So if I say:
>
> foo *@args;
>
> or if I say:
>
> foo(*@args);
>
> I still mean the same thing: shuck the array and get those args out
> here, even the pairs.

The trouble is, an array doesn't contain enough information:

Compare:
foo( (a=>1), b=>2 );

With
@args = ( (a=>1), b=>2 );
foo( *@args );

If we have an arglist ctor, then we could have

@args = arglist( (a=>1), b=>2 );
foo( *@args);

say @args.perl
## (
## (a=>1) but is_positional,
## (b=>2) but is_named,
## )


but without such a constructor, it would be difficult to DWIM correctly.

Of course, for the case of $?ARGS, constructing the array with
appropriate properties wouldn't be a problem.

Mark Reed

unread,
Oct 10, 2005, 1:48:20 PM10/10/05
to Ingo Blechschmidt, perl6-l...@perl.org

On 2005-10-10 13:36, "Ingo Blechschmidt" <ibl...@web.de> wrote:
> Under the proposal, a Pair object doesn't have any special
> magic

Right. So under this proposal, the "key => value" syntax is overloaded: in
some contexts it creates a Pair object, and in others it assigns a value to
a named parameter, and parentheses are the disambiguating mechanism to get
the former behavior in the latter context. Meanwhile, a reference to a Pair
object occurring in an argument list does not interact with the
named-parameter mechanism at all.

At least, not by default. It would be desirable to have a way to flatten a
hash/list of Pairs/whatever in such a way that it *does* map key names to
named parameters.


Juerd

unread,
Oct 10, 2005, 1:53:37 PM10/10/05
to perl6-l...@perl.org
Ingo Blechschmidt skribis 2005-10-10 19:36 (+0200):

> my @array = (42, "hi", (a => 23));

It is worth pointing out that the inner parens here are merely for
grouping: this information is lost afterwards, hence this:

> foo *@array; # same as

shouldn't be

> foo 42, "hi", (a => 23); # three positional params (Int, Str, Pair)

but instead

foo 42, "hi", a => 23 # two positional args, one named.

OR pairs need to remember whether they were originally in parens. This
is very doable, but whether we want or need it is very arguable.

(Very little sidenote: parameters are expected, arguments are passed. In
the signature, you have parameters, in the call, you have arguments.
However, in the case of a named argument, it does make some sense to
call the name parameter and the value argument, resulting in having both
in the call.)

Ingo Blechschmidt

unread,
Oct 10, 2005, 1:54:04 PM10/10/05
to perl6-l...@perl.org
Hi,

Mark Reed wrote:
> On 2005-10-10 13:36, "Ingo Blechschmidt" <ibl...@web.de> wrote:
>> Under the proposal, a Pair object doesn't have any special
>> magic
>
> Right. So under this proposal, the "key => value" syntax is
> overloaded: in some contexts it creates a Pair object, and in others
> it assigns a value to a named parameter, and parentheses are the
> disambiguating mechanism to get
> the former behavior in the latter context. Meanwhile, a reference to
> a Pair object occurring in an argument list does not interact with the
> named-parameter mechanism at all.

Exactly.

> At least, not by default. It would be desirable to have a way to
> flatten a hash/list of Pairs/whatever in such a way that it *does* map
> key names to named parameters.

Yep:

foo *%hash; # keys of %hash taken as named parameters
foo *hash(@array_of_pairs);
# @array_of_pairs's pairs taken as named parameters


--Ingo

Ingo Blechschmidt

unread,
Oct 10, 2005, 1:59:22 PM10/10/05
to perl6-l...@perl.org
Hi,

Dave Whipp wrote:
> Austin Hastings wrote:
>> How about "perl should DWIM"? In this case, I'm with Juerd: splat
>> should pretend that my array is a series of args.
>>
>> So if I say:
>>
>> foo *@args;
>>
>> or if I say:
>>
>> foo(*@args);
>>
>> I still mean the same thing: shuck the array and get those args out
>> here, even the pairs.
>
> The trouble is, an array doesn't contain enough information:
>
> Compare:
> foo( (a=>1), b=>2 );
>
> With
> @args = ( (a=>1), b=>2 );
> foo( *@args );

my @args = ( (a => 1), b => 2 ); # is sugar for
my @args = ( (a => 1), (b => 2) );
# We can't stuff named arguments into an array, only pairs.
# Named arguments are neither objects nor some other data type,
# they're purely syntactical.

> If we have an arglist ctor, then we could have
>
> @args = arglist( (a=>1), b=>2 );
> foo( *@args);
>
> say @args.perl
> ## (
> ## (a=>1) but is_positional,
> ## (b=>2) but is_named,
> ## )
>
>
> but without such a constructor, it would be difficult to DWIM
> correctly.

Yep, see Luke's tuple proposal [1]:

my $tuple = ( (a => 1), b => 2 );
foo *$tuple; # same as
foo( (a => 1), b => 2 ); # one positional argument (a Pair) and
# the named parameter "b"


--Ingo

[1] http://svn.openfoundry.org/pugs/docs/notes/theory.pod
/Tuples

Ingo Blechschmidt

unread,
Oct 10, 2005, 2:08:03 PM10/10/05
to perl6-l...@perl.org
Hi,

Juerd wrote:
> Ingo Blechschmidt skribis 2005-10-10 19:36 (+0200):
>> my @array = (42, "hi", (a => 23));
>
> It is worth pointing out that the inner parens here are merely for
> grouping: this information is lost afterwards, hence this:
>
>> foo *@array; # same as
>
> shouldn't be
>
>> foo 42, "hi", (a => 23); # three positional params (Int, Str,
>> Pair)
>
> but instead
>
> foo 42, "hi", a => 23 # two positional args, one named.
>
> OR pairs need to remember whether they were originally in parens. This
> is very doable, but whether we want or need it is very arguable.

Luckily, this is not needed, see my response to Dave [1]:

Because named arguments are purely syntactic (i.e., they are not objects
or some other kind of data type), you can't stuff them into an array
(or a scalar, for that matter).

# (assuming => binds thighter than =)
my $scalar = a => 1; # sugar for
my $scalar = (a => 1);

my @array = (42, a => 1); # sugar for
my @array = (42, (a => 1));

Named arguments can -- under the proposal -- only ever exist in calls.


--Ingo

[1] http://www.nntp.perl.org/group/perl.perl6.language/23438

Juerd

unread,
Oct 10, 2005, 2:22:06 PM10/10/05
to perl6-l...@perl.org
Ingo Blechschmidt skribis 2005-10-10 20:08 (+0200):

> Named arguments can -- under the proposal -- only ever exist in calls.

Which leaves us with no basic datastructure that can hold both
positional and named arguments. This is a problem because in a call,
they can be combined.

An array could hold both, but with only one small and minor
inconvenience: pairs are either all positional, or all named. I
sincerely believe that this is a feature, not a problem, because arrays
are singledimensional, and having pairs mean two different things on the
same level is, as this new proposal also indicates, confusing at best.

Juerd

unread,
Oct 10, 2005, 2:24:48 PM10/10/05
to perl6-l...@perl.org
Ingo Blechschmidt skribis 2005-10-10 19:59 (+0200):

> my @args = ( (a => 1), b => 2 ); # is sugar for
> my @args = ( (a => 1), (b => 2) );

Please, no. Please let the pair constructor be =>, not (=>). There is
really no need for this operator to consist of both infix and circumfix
parts. Please leave the parens for grouping (and in calls: breaking
recognition).

Ingo Blechschmidt

unread,
Oct 10, 2005, 2:32:25 PM10/10/05
to perl6-l...@perl.org
Hi,

Juerd wrote:
> Ingo Blechschmidt skribis 2005-10-10 19:59 (+0200):
>> my @args = ( (a => 1), b => 2 ); # is sugar for
>> my @args = ( (a => 1), (b => 2) );
>
> Please, no. Please let the pair constructor be =>, not (=>). There is
> really no need for this operator to consist of both infix and
> circumfix parts. Please leave the parens for grouping (and in calls:
> breaking recognition).

Err, of course! The parens around "b => 2" should make clear that "b =>
2" is not a named argument, but a pair. Outside of calls, the parens
are only for grouping:

my @args = (b => 2); # same as
my @args = ((b => 2)); # same as
my @args = ((((b => 2))));


--Ingo

Uri Guttman

unread,
Oct 10, 2005, 2:40:14 PM10/10/05
to Juerd, perl6-l...@perl.org
>>>>> "J" == Juerd <ju...@convolution.nl> writes:

J> Ingo Blechschmidt skribis 2005-10-10 19:59 (+0200):


>> my @args = ( (a => 1), b => 2 ); # is sugar for
>> my @args = ( (a => 1), (b => 2) );

J> Please, no. Please let the pair constructor be =>, not (=>). There is
J> really no need for this operator to consist of both infix and circumfix
J> parts. Please leave the parens for grouping (and in calls: breaking
J> recognition).

he isn't saying that. the example shows the b => 2 is fine and will be
parsed as if it were ( b => 2 ). the point is how pairs in an array are
splatted or not to names args. and if i get it right, *hash( @args ) is
what is needed to convert an array of pairs to be used as named params.

Ingo Blechschmidt

unread,
Oct 10, 2005, 2:47:21 PM10/10/05
to perl6-l...@perl.org
Hi,

Juerd wrote:
> Ingo Blechschmidt skribis 2005-10-10 20:08 (+0200):
>> Named arguments can -- under the proposal -- only ever exist in
>> calls.
>
> Which leaves us with no basic datastructure that can hold both
> positional and named arguments. This is a problem because in a call,
> they can be combined.

Very true. This is why we need Luke's Tuple proposal [1]. Basically:

my $tuple = (a => 1, (b => 2)):{ ...block... }; # $tuple.isa(Tuple)
# Tuples are ordinary objects -- they can be stored
# in scalars, arrays, etc.

# But splatting tuples unfolds their magic:
foo(*$tuple); # same as
foo(a => 1, (b => 2)):{ ...block...};
# named arg "a", positional pair (b => 2),
# adverbial block { ...block... }

# (Yep, under the current proposal, tuple construction conflicts
# with list/array construction. FWIW, I'd be fine with
# using Tuple.new(...) as the tuple constructor.)


--Ingo

[1] http://svn.openfoundry.org/pugs/docs/notes/theory.pod

Austin Hastings

unread,
Oct 11, 2005, 2:08:19 AM10/11/05
to p6l
Ingo Blechschmidt wrote:

>Juerd wrote:
>
>
>>Ingo Blechschmidt skribis 2005-10-10 20:08 (+0200):
>>
>>
>>>Named arguments can -- under the proposal -- only ever exist in
>>>calls.
>>>
>>>
>>Which leaves us with no basic datastructure that can hold both
>>positional and named arguments. This is a problem because in a call,
>>they can be combined.
>>
>>
>
>Very true. This is why we need Luke's Tuple proposal [1].
>

Luke's Tuple proposal, aka Luke's Grand Unified Object Model, is way not
what we need for this. As far as I can see, LGUOM is an expression of
"Haskell envy" of brobdingnagian proportion. A rule that says "splatting
a list coerces all pairs into named args" works just fine. The
corresponding rule, "accessing the parameters to your sub as a list (not
using *%args) coerces all named args to pairs". Presto! Reversible, etc.

An alternative might be PHP-style arrays. But nobody wants that.

>Basically:
>
> my $tuple = (a => 1, (b => 2)):{ ...block... }; # $tuple.isa(Tuple)
> # Tuples are ordinary objects -- they can be stored
> # in scalars, arrays, etc.
>
> # But splatting tuples unfolds their magic:
> foo(*$tuple); # same as
> foo(a => 1, (b => 2)):{ ...block...};
> # named arg "a", positional pair (b => 2),
> # adverbial block { ...block... }
>
> # (Yep, under the current proposal, tuple construction conflicts
> # with list/array construction. FWIW, I'd be fine with
> # using Tuple.new(...) as the tuple constructor.)
>
>
>--Ingo
>
>[1] http://svn.openfoundry.org/pugs/docs/notes/theory.pod
>
>

Tuple construction conflicts with a lot of things. Given the amount of
new (to me, anyways) syntax proposed in the rest of the document, I'm
surprised that LQe didn't unify lists and tuples (or push list
construction elsewhere).

=Austin

Stuart Cook

unread,
Oct 11, 2005, 8:00:55 AM10/11/05
to p6l
On 11/10/05, Austin Hastings <Austin_...@yahoo.com> wrote:
> Luke's Tuple proposal, aka Luke's Grand Unified Object Model, is way not
> what we need for this. As far as I can see, LGUOM is an expression of
> "Haskell envy" of brobdingnagian proportion.

The reason I refrained from linking to theory.pod was that I didn't
want people getting distracted by a document that's 90% irrelevant to
what we're discussing here.

That other 10%, though, is Tuples--and they're exactly what's needed
for representing an argument-'list' in its entirety. That is, after
all, a large part of what they were designed for.

> A rule that says "splatting
> a list coerces all pairs into named args" works just fine. The
> corresponding rule, "accessing the parameters to your sub as a list (not
> using *%args) coerces all named args to pairs". Presto! Reversible, etc.

1)
What happens if that list is lazy?
You'd have to force the entire thing, just to check if there were any
pairs hiding in it.
What if it's an infinite list?
What if you can't know whether it's infinite or not?

2)
What if the list contains pairs, but you want to pass them as positionals?
What if it might contain pairs, but you're not sure?
What if you introduce a new named parameter (or change a parameter
name), and what you thought was a positional pair now becomes a named
arg?

Your suggestion would involve re-introducing some of the 'magic' that
real experience suggests we should be trying desperately to get away
from.

And look, if you really wanted to, you could define your own
splat-style operator that works exactly as you describe. But I don't
think it should be the default.

> An alternative might be PHP-style arrays. But nobody wants that.

The key difference is that while a PHP-style array can't decide
whether it's an array or a hash, a Tuple *knows* that it has to be
both (and more), in order to accurately represent the full power of
Perl 6's argument system.

(Also, Tuples might end up being immutable, but don't quote me on that.)

> Tuple construction conflicts with a lot of things. Given the amount of
> new (to me, anyways) syntax proposed in the rest of the document, I'm
> surprised that LQe didn't unify lists and tuples (or push list
> construction elsewhere).

He very nearly does, actually (albeit with a handwave). But Tuple
syntax (and the rest of theory.pod) is largely irrelevant here. (I
personally think Ingo's `Tuple.new` might be sufficient.)


Stuart

Ingo Blechschmidt

unread,
Oct 11, 2005, 10:15:45 AM10/11/05
to perl6-l...@perl.org
Hi,

Stuart Cook wrote:
> On 11/10/05, Austin Hastings <Austin_...@yahoo.com> wrote:
>> A rule that says
>> "splatting
>> a list coerces all pairs into named args" works just fine. The
>> corresponding rule, "accessing the parameters to your sub as a list
>> (not using *%args) coerces all named args to pairs". Presto!
>> Reversible, etc.
>

> 2)
> What if the list contains pairs, but you want to pass them as
> positionals? What if it might contain pairs, but you're not sure?
> What if you introduce a new named parameter (or change a parameter
> name), and what you thought was a positional pair now becomes a named
> arg?
>
> Your suggestion would involve re-introducing some of the 'magic' that
> real experience suggests we should be trying desperately to get away
> from.

Exactly. I'd like to add that, under the proposal, you always know what
things are passed how, only by looking for a "*".

foo $var; # always positionally, even if $var isa Pair
foo *$pair; # always named

foo *@array; # always positionally
foo *%hash; # always named (hash keys taken as parameter names)

Previously, you wasn't able to know whether you passed something
positionally or by name:

sub bar ($x) { grtz $x }
bar 42; # 42 passed to &grtz positionally
bar a => 42; # either the pair (a => 42) passed to &grtz
# positionally or the number 42 passed by name

Under the new proposal, "grtz $x" always passes $x positionally. You
don't need &grtz's signature, nor do you need to know $x's type (is $x
a Pair?). Compare this with the old semantics:

grtz $x;
# $x is not a Pair? ==> $x passed positionally
# else ==>
# &grtz expects a Pair as its first positional parameter?
# ==> $x passed positionally
# else ==>
# &grtz's signature lists a parameter named $x.key?
# ==> $x.value passed by name
# else
# ==> $x passed positionally

> And look, if you really wanted to, you could define your own
> splat-style operator that works exactly as you describe. But I don't
> think it should be the default.

Right. Under the proposal, you can -- *if you want to* -- use pairs
stuffed in arrays as named arguments:

foo *hash(@array_of_pairs);
# @array_of_pairs's pairs used as named args

foo *@array_of_pairs;
# @array_of_pairs's pairs used positionally

But if we made *@array mean that...

* ...@array's pairs are always taken as named arguments,
there wouldn't be a simple way to pass pairs positionally.

* ...@array's pairs are always taken as pairs,
there wouldn't be a simple way to use the pairs as named arguments.

* ...@array's pairs are taken as pairs or named arguments,
depending on the called subroutine (does it accept named params?
Do some parameters specifically want a Pair? etc.), we'd introduce
non-local non-determinism to a quite important part of the language.


--Ingo

TSa

unread,
Oct 11, 2005, 12:49:33 PM10/11/05
to perl6-l...@perl.org
HaloO,

Larry Wall wrote:
> It still has to figure out how to reconcile the named arguments
> with the positional parameters, of course, unless someone has
> made sufficient representation to the compiler that all calls to
> a particular short name have particular named parameters that are
> guaranteed to be in the same position everywhere, in which case the
> compiler is allowed to simply translate them to positionals on the
> call end.

Does that mean that a named binding excludes a positional one and
vice versa? I would consider that too much of a burden that tries
to solve the unsolvable problem of meeting unstated assumptions ;)


The thing I try to get at is the unification of classes and their
instances on the one hand and subs and their invocations on the
other.

Let's take the four sigiled vars $_, @_, %_ and &_ and assume that
they always contain the current state of affairs. Let's say they are
the "registers" of the virtual machine. Everything else is the memory
that refers to itself in a what not messy way. Memory locations not
rooted in the four registers are garbage collected eventually.

Making a goto kind of call just means putting a new address into &_.
At the statement level there's of course an automatic goto to the
next instruction.

A sub kind of call with parameters means messing with $_, @_ and %_
prior to making the jump. The return values are passed out by messing
with $_, @_ and %_ in the sub. With CPS there actually is no returning.
It's just the next jump. Well, the handling of the four magicals is
more complicated than that. There'll be lexical binding, temping etc.
And how about rules and grammars? Is there a $/, @/, %/ and &/ quadriga?

Method dispatch means basing the selection of the address
to be put into &_ on the content of $_, @_ and %_.


Not considering dispatch and the topic for now I come back to
the problem of this thread: the constructor call for an invocation
of a sub stored in &_. The task of the compiler is to output code
that doesn't violate structural type constraints extracted from
the source while preserving unspecificity as much as possible.

The first set of constraints comes from the signature of &_ and the
second from the *syntactical* structure of the arguments. The left
to right order gives the positional structure while the adverbial
pairs and the autoquoting version of fat arrow give the named or keyed
structure. Splatted terms are actually lazily evaluated code fragments
that insert information into the magicals prior to this matching.
Double splat does so eagerly. The prefix fundamental type enforcers
?, + and ~ also produce structural items as a side effect. So do most
circumfix operators like [], '' or "". The parens are for grouping
only, they are transparent to structural typing! The loose precedence
separators , and ; never take keyed args. I think it makes sense to
exclude them from overloading. They might be a context sensitive parser
concept, actually.

Well, and at some point prior to bindind the args to the params
the trait blocks like ENTER and PRE are called. And I wonder how
labels inside the sub's block can be used to enter it through
different paths:

sub through
{
first: say "first"; return;
second: say "second"; return;
third: say "third"; return;
}

through :third; # prints "third"?
through; # prints "first"?


Obviously neither the compiler nor the virtual machine will have
difficulties with the above procedure. Also the programmers can
shy away from beeing specific on the caller side or the callee
side by splatting. Note that what I call structural type match is
only an arity and key match. Type constraints are checked only if
the structure fits!

From this thread I gather that the case of a pair hidden in an array
is the most debated one:

my @array = ( 1, two => 2, 3 );

I hope, we all agree that +@array == 3. But is @array<two> == 2?
If yes, what shall happen with

foo( *@array );

when foo requires exactly three params?

sub foo ($x, $y, $z) {...}

And how shall the arity 2..3 be handled?

sub foo ($x, $y, ?$z) # structure is foo:($,$,?$) without param names
{
$x eqv 1; # yes
$y eqv (two => 2) && $z eqv 3; # this?
$y eqv 3 && $z eqv undef; # or this?
}

How about a named optional with my preferred keyed item twigil :$
where actually the key and variable name might differ as in :two$z?
Perhaps that might be spelled :two($z) and allow the fat arrow
syntax two => $z as well.

sub foo ($x, $y, :$two) # structure is foo:($,$,:two) without param names
# S06: ($x, $y, +$two)
# ($x, $y, two => $z)
{
$x eqv 1; # yes
$y eqv (two => 2) && $two eqv 2; # this?
$y eqv 3 && $two eqv 2; # or this?
}

My 'Seven Sigils of Perl6' idea also nicely delivers an invocant markup
in methods:

method foo (.$self, $x, $y, two => $z) {...}

Without the multi prefix

method blahh ( .$first, .$second ) {...} # perhaps without comma?
# S12: ( $first: $second:)

gives the left biased dispatch, while

multi method blahh ( .$first, .$second ) {...}

aims at MMD. A method form without a dotted item assumes .$_ perhaps?

A strict parse time separation into zones for invocants, required and
optional positionals, then keyed and finally the slurpy part in definitional
forms makes sense, I think. But we could allow overlap between optional and
keyed:

sub foo ($x, $y, ?:$opt, :$key) {...}

Which means a positional arity 2..3 and a keyed arity of 0..4 if the
identifiers $x and $y are known outside of the definition. With a stub

sub foo ($, $, ?:opt, :key) {...}

the keyed arity is 0..2 or perhaps 2..4 if the keyed arity includes
the positional. Can we define a way to retrieve this information
from foo nicely?

Infinite arity is of course indicated with *. The sigils determine only
how the inside wants to access the variadic part which is only disjointly
split into positional and keyed if both types of sigils are present. The
positional ones are *$, *& and *@ and keyed params are indicated by *:$,
*:& and *%. Should a slurpy array do double duty if no slurpy hash is there?
Or should such an overlap be requested explicitly with *:@array in the sig?

In the end a signature has 1 + 2 + 2 parts or zones from left to right:

1) finite invocants
2) finite positionals
3) finite keyed
4) infinite positionals
5) infinite keyed

A nice syntax for this structural type could be
&foo:( .i..I --> p..P :k..K --> r..R ) where
i and I are the min and max number of invocants,
p and P are the min and max positional arity,
k and K are the min and max keyed arity,
r and R are the min and max return arity.

..P, ..K and ..R can be Inf, ..I is finite and they are optional if equal
to their lowercase partner. For a sub i == 0 and the left --> is optional.
For a non-multi method i == 1 and I == 1 but the dot is mandatory when used
on a &var invocation term. In a method definition this part is derived from
the lexical scope when omitted.

The right --> is optional and defaults to --> 0..Inf then. The keyed part
including the colon is optional and defaults to 0..0 for subs and 0..Inf for
methods, I guess? The reverse applies to the positionals where subs default
to 0..Inf and methods to 0..0. The central part is subtyped contravariantly,
the outer parts covariantly after structural fitting.

The --> can be repeated to the left and right. But note that
extending into the dispatch part at least needs a dot:

&foo:( . --> . --> 3 --> 4 ) $x, $y, $z,1,2, *<a b c d x y z>;

This means that the coderef &foo is dispatched on $x and has to yield a
method that is then dispatched on $y which has to yield a sub that takes
three required params. These receive $z, 1 and 2 respectively and the sub
has to return a coderef that requires 4 params. These would receive
'a' .. 'd' respectively. But the superflous 'x' .. 'z' cause an
arity error. The latter could be prevented with writing ( --> 4..Inf)
there. But note that there are quite many checks deferred until runtime
nonetheless.

So much, so good.

There's another funny thing that I haven't thought through, yet. If &_ is
the post-dispatch, post-binding coderef to the innermost call instance
then first of all a plain _ is just a call through that ref maintaining
the environment or so.

More interestingly the invocant part is pre-bound, and that might
lead to the natural re-call of current method syntax

_();

or if you push the parens one char rightwards

_.();

After the dot appeared further right shiftings reveal nothing new,
of course:

_ .();

Well, and the non-invocant params can be bound to new arguments

_ .(1,2);

in method syntax or with listop syntax

_ 1,2;

Named args also work as usual:

_ 1, :blahh(13), 23, xx => 2';

Ohh, and in a binop instance

$x _ $y;

just means to call the current operator with two new args. A bit further
down this road we observe that the method sigil requests a re-dispatch

$x._; # definitely weird looking

._; # same on $_ or $?SELF

Somewhat off-topic, sorry.
--
$TSa.greeting := "HaloO"; # mind the echo!

TSa

unread,
Oct 12, 2005, 12:41:12 PM10/12/05
to perl6-l...@perl.org
HaloO,

Ingo Blechschmidt wrote:
> Exactly. I'd like to add that, under the proposal, you always know what
> things are passed how, only by looking for a "*".
>
> foo $var; # always positionally, even if $var isa Pair
> foo *$pair; # always named

But where is the name? Is it 'pair'? Like in

foo :pair($pair);

or dynamically through

foo $pair.key => $pair.value;

assuming that precedence of => is tighter than foo's. As I lengthyly ranted
elsewhere in this thread the splat should just defer the structural
callability check until runtime. Well, and since everybody seems to be
happy with .$pair denoting a call through a hardref stored in $pair, I
don't understand why :$pair is not (yet) denoting a hard pairref. Both forms
beeing interpreted in the context of the term to their *immediate* left
which in turn is interpreted leftwards. And both forms fail if the
assumptions about the type of value $pair will eventually refer to
won't hold. The difference to the splat form is eagerness:

foo :$pair; # eager
foo *$pair; # lazy

and op versus sigil

foo : $pair; # syntax error like $ pair
foo (: $pair); # same
foo: $pair; # labeled statement

foo * $pair; # infix
foo (* $pair); # prefix
(foo *) $pair; # postfix, which I guess doesn't exist


If full uncertainty isn't your thing, you might instruct the type system
to make sure that $pair at least doesn't fail you on pairhood

my Pair $pair;

foo $pair; # syntactically an item, thus a positional call
foo *$pair; # guarranteed pair after splatting

But of course the call could still fail because there is no parameter
under the key of $pair. Now I think you could instruct the kind type
system also to oversee the meeting of this constraint with

my Pair of foo $pair;

foo $pair; # you guessed it, positional call
foo *$pair; # always delivers $pair.value into $pair.key
# parameter of foo

Which might be a too sophisticated variable for your purposes if it
also oversees the values to put into $pair depending on the current
key. This might reduce usability of $pair while you are not calling
foo with it. Thus an intermediate choice could be

my Pair where .key of foo $pair;
# my $pair is Pair where .key of foo; # same
# my Key of foo $pair; # abbreviation of same?

foo *$pair; # name hits home, but type error is possible

If you know that all named params of foo are integers you could
oblige yourself to adhere to this with

my $pair is Pair of Int where .key of foo;

And yes, I know that this should be written

my $pair is Pair of Int where { .key of foo };

where the ; might be optional. Is it?


The unsigiled foo there is actually shying away from full dynamism:

&foo *$bar;

This is almost meaningless in itself because it states: "Try to do
what &foo tells you to do with whatever you find in $bar when you try
to do so." But the code that the compiler generates is actually quite
short! E.g. a single call instruction if &foo and $bar are already in
VM registers. Only the outcome is uncertain ;)


> foo *@array; # always positionally

This makes perfect sense to me if you mean that the positionals
that foo requests are satisfied in the order provided by @array
without exceptions for pairs, not to mention subtypes of pairs
or things that do the Pair role etc.


> foo *%hash; # always named (hash keys taken as parameter names)

So that shall fail at compile time if foo has *anonymous* positionals?
E.g. a sig ($,$,$) or would there be a desparate attempt to call it as

foo %hash<0>, %hash<1>, %hash<2>;

or aiming at whatever .[Int] means on a hash:

foo %hash[0], %hash[1], %hash[2];

BTW, I would write a keyed sig as &foo:(:x,:y,:z).


> Previously, you wasn't able to know whether you passed something
> positionally or by name:
>
> sub bar ($x) { grtz $x }
> bar 42; # 42 passed to &grtz positionally
> bar a => 42; # either the pair (a => 42) passed to &grtz
> # positionally or the number 42 passed by name
>
> Under the new proposal, "grtz $x" always passes $x positionally. You
> don't need &grtz's signature, nor do you need to know $x's type (is $x
> a Pair?).

Yep. But you could attempt to dispatch .key on $x in grtz:

sub grtz ($item)
{
say $x.key;
}

and get a printout of 'Undef of Key' or so and 'a' respectively.
HiHi, or a 'method not understood' exception if .key is not applicable
to 42 ;)


> Compare this with the old semantics:
>
> grtz $x;
> # $x is not a Pair? ==> $x passed positionally
> # else ==>
> # &grtz expects a Pair as its first positional parameter?
> # ==> $x passed positionally
> # else ==>
> # &grtz's signature lists a parameter named $x.key?
> # ==> $x.value passed by name
> # else
> # ==> $x passed positionally
>

Stuart Cook wrote:
>>And look, if you really wanted to, you could define your own
>>splat-style operator that works exactly as you describe. But I don't
>>think it should be the default.

I think that is difficult *without* parser support because
a purely prefix thingy doesn't get the coderef the flattened
array goes to. Well, and it can't be infix either because it
first of all conflicts with numeric multiplication and would
require the coderef beeing non-bare syntactically.

foo * @array; # multiply retval of foo with arity of @array or so

&foo * @array; # &infix:<*>:(Code,Array)(&foo,@array);

BTW, I parse the construct in the last comment as

1) there is a &infix code multitude
2) constrain that to the ones with identifier '*'
3) further constrain it to the ones that take a Code and an Array
4) then dispatch on the actual types of &foo and @array

In a certain way I would hope that

&foo &infix @array, :<*> :(Code,Array); # note the comma!

and

&foo &infix :<*> :(Code,Array) @array; # note: no comma

mean the same. Well and it should be writeable with fat comma, too

&foo ((Code,Array) => (* => &infix)) @array;


> Right. Under the proposal, you can -- *if you want to* -- use pairs
> stuffed in arrays as named arguments:
>
> foo *hash(@array_of_pairs);
> # @array_of_pairs's pairs used as named args

This hash function there is hardly the same as the one from S06, that
takes every other pair from @array_of_pairs, converts *the pair*
to a key---which might preserve the key actually---and combines it
with the next entry from the array as value?

@AoP = (a => 'a', b => 'b', c => 'c', d => 'd');
%hash = hash @AoP;
# = (AoP[0] => AoP[1], AoP[2] => AoP[3]);
# = ( a => 'b' , c => 'd' );

+%hash == 2; # true?

foo *%hash; # foo( a => 'b', c => 'd')

> foo *@array_of_pairs;
> # @array_of_pairs's pairs used positionally
>
> But if we made *@array mean that...
>
> * ...@array's pairs are always taken as named arguments,
> there wouldn't be a simple way to pass pairs positionally.
>
> * ...@array's pairs are always taken as pairs,
> there wouldn't be a simple way to use the pairs as named arguments.

I might not sure that I get your idea correctly but haven't you shifted
the magical pair filtering into your hash function? And the syntax
you've picked is also counter-intuitive at least to my arguably strange
intuition. That is, foo should be an argument to the pair filter:

# sub, multi form
pair_filter_call( &foo, @array_of_pairs );

# listop form
pair_filter_call &foo, @array_of_pairs;

# named arg forms
pair_filter_call code => &foo, data => @array_of_pairs;
pair_filter_call:code(&foo):data(@array_of_pairs);

# method forms
&foo.pair_filter_call( @array_of_pairs );
@array_of_pairs.pair_filter_call( &foo );
( &foo, @array_of_pairs ).pair_filter_call;

Since *% as an operator name isn't taken you could

&infix:<*%> ::= &pair_filter_call;

and get

&foo *% @array;


> * ...@array's pairs are taken as pairs or named arguments,
> depending on the called subroutine (does it accept named params?
> Do some parameters specifically want a Pair? etc.), we'd introduce
> non-local non-determinism to a quite important part of the language.

It is *NOT* non-determinism! It is under-constraint behaviour.
But that is considered a feature by the Perl 6 community, isn't it?
Given the exact same &foo and @array_of_pairs a call

foo *@array_of_pairs;

in a fixed environment should give the same result---always.

After all you have to know something about foo's signature to call
it relieably! Late binding is cool, but some expect the arguments
to parameters binding to be performed before the program stops running.
But lazyness ultimately means binding args in the time after a successfull
run of a particular invocation of the program. And prefix:<*> is the
lazyness operator if I remember correctly :)

Ingo Blechschmidt

unread,
Oct 12, 2005, 1:42:24 PM10/12/05
to perl6-l...@perl.org
Hi,

TSa wrote:
> Ingo Blechschmidt wrote:
>> Exactly. I'd like to add that, under the proposal, you always know
>> what things are passed how, only by looking for a "*".
>>
>> foo $var; # always positionally, even if $var isa Pair
>> foo *$pair; # always named
>
> But where is the name? Is it 'pair'? Like in
>
> foo :pair($pair);

No.

> or dynamically through
>
> foo $pair.key => $pair.value;

Yep.

> assuming that precedence of => is tighter than foo's.

I think it is.

> As I lengthyly ranted elsewhere in this thread the splat should just
defer the
> structural callability check until runtime. Well, and since everybody
> seems to be happy with .$pair denoting a call through a hardref stored
> in $pair, I don't understand why :$pair is not (yet) denoting a hard
> pairref. Both forms beeing interpreted in the context of the term to

Um, sorry, I don't understand... The only syntax I know of where a $
follows a . is calling method references:

my $meth = method (Foo $self: ...) {...};
$foo.$meth(...);

(But this syntax doesn't have, obviously, anything to do with
magical/non-magical pairs.)

> If full uncertainty isn't your thing, you might instruct the type
> system to make sure that $pair at least doesn't fail you on pairhood
>
> my Pair $pair;

Yep.

> foo $pair; # syntactically an item, thus a positional call
> foo *$pair; # guarranteed pair after splatting

>> foo *@array; # always positionally


>
> This makes perfect sense to me if you mean that the positionals
> that foo requests are satisfied in the order provided by @array
> without exceptions for pairs, not to mention subtypes of pairs
> or things that do the Pair role etc.

Yep, it's very important that Pairs are not exceptions.

>> foo *%hash; # always named (hash keys taken as parameter names)
>
> So that shall fail at compile time if foo has *anonymous* positionals?

Assuming that anonymous positionals exist, yes, I think so.

>> Previously, you wasn't able to know whether you passed something
>> positionally or by name:
>>
>> sub bar ($x) { grtz $x }
>> bar 42; # 42 passed to &grtz positionally
>> bar a => 42; # either the pair (a => 42) passed to &grtz
>> # positionally or the number 42 passed by name
>>
>> Under the new proposal, "grtz $x" always passes $x positionally. You
>> don't need &grtz's signature, nor do you need to know $x's type (is
>> $x a Pair?).
>
> Yep. But you could attempt to dispatch .key on $x in grtz:
>
> sub grtz ($item)
> {
> say $x.key;
> }
>
> and get a printout of 'Undef of Key' or so and 'a' respectively.
> HiHi, or a 'method not understood' exception if .key is not applicable
> to 42 ;)

Yep, of course. Pairs are, when not splatted with *, normal instances of
normal classes. (And when pairs are splatted, they are no longer pairs,
but syntactical constructs. (This might of course be implemented using
some class in the compiler, but this is an implementation detail.))

> Stuart Cook wrote:
>>>And look, if you really wanted to, you could define your own
>>>splat-style operator that works exactly as you describe. But I don't
>>>think it should be the default.
>
> I think that is difficult *without* parser support because
> a purely prefix thingy doesn't get the coderef the flattened
> array goes to.

Right, also &prefix:<*> can be faked as a normal subroutine (the PIL to
JavaScript compiler does this currently [1]), it has to be some kind of
grammatical rule or perhaps a macro if we want it to be implemented
properly.

>> Right. Under the proposal, you can -- *if you want to* -- use pairs
>> stuffed in arrays as named arguments:
>>
>> foo *hash(@array_of_pairs);
>> # @array_of_pairs's pairs used as named args
>
> This hash function there is hardly the same as the one from S06, that
> takes every other pair from @array_of_pairs, converts *the pair*
> to a key---which might preserve the key actually---and combines it
> with the next entry from the array as value?

Hm. I thought the hash() sub would be a bit more DWIMmy, so it can be
used for desugaring:

my %hash = (a => 1, "b",2, "c"); # desugared to
my %hash = hash(a => 1, "b",2, "c"); # which means
my %hash = (a => 1, b => 2, c => undef);

# thus:
sub hash (*@things) returns Hash {
my %hash;

while shift @things -> $thing {
given $thing {
when Pair { %hash{$thing.key} = $thing.value }
default {
my $value = shift @things;
%hash{$thing} = $value;
}
}
}

%hash;
}

But, looking at S06, the reference implementation of S06 isn't that
DWIMmy. Dunno whether this is simply a oversight in S06 or whether it
has been purposefully left out.

> @AoP = (a => 'a', b => 'b', c => 'c', d => 'd');
> %hash = hash @AoP;
> # = (AoP[0] => AoP[1], AoP[2] => AoP[3]);
> # = ( a => 'b' , c => 'd' );
>
> +%hash == 2; # true?

With my &hash, +%hash would be 4.

>> But if we made *@array mean that...
>>
>> * ...@array's pairs are always taken as named arguments,
>> there wouldn't be a simple way to pass pairs positionally.
>>
>> * ...@array's pairs are always taken as pairs,
>> there wouldn't be a simple way to use the pairs as named arguments.
>
> I might not sure that I get your idea correctly but haven't you
> shifted the magical pair filtering into your hash function?

Not quite. Under the proposal, you can be absolutely sure that you're
passing things positionally unless you explicitly use the splat
operator. And when you write "foo *%hash", you know exactly what
parameters are passed by names (as you can call %hash.keys).

Previously, you were not able to detect whether you pass things by name
unless you looked at the type of thing you're passing and the signature
of the sub you are calling.

>> * ...@array's pairs are taken as pairs or named arguments,
>> depending on the called subroutine (does it accept named params?
>> Do some parameters specifically want a Pair? etc.), we'd introduce
>> non-local non-determinism to a quite important part of the
>> language.
>
> It is *NOT* non-determinism! It is under-constraint behaviour.
> But that is considered a feature by the Perl 6 community, isn't it?
> Given the exact same &foo and @array_of_pairs a call
>
> foo *@array_of_pairs;
>
> in a fixed environment should give the same result---always.

Yes, of course, sorry, I misused the term "determinism". I meant that
you, as a subroutine writer, can't know how things will end up being
passed:

sub foo ($thing) { bar $thing }
# Either $thing is passed positionally to &bar or
# $thing.value is passed by name ($thing.key).

So s[determinism][clear/manageable] please :)


--Ingo

0 new messages