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

[svn:perl6-synopsis] r13549 - doc/trunk/design/syn

5 views
Skip to first unread message

la...@cvs.perl.org

unread,
Jan 30, 2007, 3:11:00 PM1/30/07
to perl6-l...@perl.org
Author: larry
Date: Tue Jan 30 12:11:00 2007
New Revision: 13549

Modified:
doc/trunk/design/syn/S09.pod

Log:
Disabled negative subscript dwimmery for all shaped arrays.
* can now take + and - operators.


Modified: doc/trunk/design/syn/S09.pod
==============================================================================
--- doc/trunk/design/syn/S09.pod (original)
+++ doc/trunk/design/syn/S09.pod Tue Jan 30 12:11:00 2007
@@ -12,9 +12,9 @@

Maintainer: Larry Wall <la...@wall.org>
Date: 13 Sep 2004
- Last Modified: 1 Oct 2006
+ Last Modified: 30 Jan 2007
Number: 9
- Version: 15
+ Version: 16

=head1 Overview

@@ -763,4 +763,54 @@

This rule applies to C<Array>, C<Hash>, and C<Scalar> container objects.

+=head1 Negative subscript dwimmery
+
+It has become the custom to use negative subscripts to indicate counting
+from the end of an array. This is still supported, but only for unshaped
+arrays:
+
+ my @a1 = 1,2,3;
+ my @a2[*] = 1,2,3;
+ @a1[-1] # 3
+ @a1[-0.5] # also 3 (uses floor semantics)
+ @a2[-1] # ERROR
+ @a2[-0.0001] # ERROR
+ @a2[0.0001] # 1
+
+For shaped arrays you must explicitly refer to the current endpoint
+using C<*>, the C<Whatever> object:
+
+ @a2[*-1] # 3
+ @a2[+*] = 1 # same as push(@a2, 1)
+
+When you use C<*> with C<+> and C<->, it creates a value of C<Whatever>
+but C<Num>, which the array subscript interpreter will interpret as the
+subscript one off the end of that dimension of the array. The lower
+right corner of a two dimesional array is C<@array[*-1, *-1]>.
+
+This policy has the fortuitous outcome that arrays declared with negative
+subscripts will never interpret negative subscripts as relative to the end:
+
+ my @array[-5..5];
+ @array[-1]; # always the 4th element, not the 11th.
+ @array[*-1]; # always the 11th element, not the 4th.
+
+Oddly, this gives us a canonical way to get the last element, but no
+canonical way to get the first element, unless
+
+ @array[*-*];
+
+works...
+
+Conjecture: we might provide a way to declare a modular subscript that
+emulates the dwimmery, perhaps by using a subset type:
+
+ subset Mod10 of Int where ^10;
+ my @array[Mod5];
+ @array[42] = 1; # sets @array[2]
+ @array[582]; # returns 1
+
+But perhaps C<Mod10> should work just like C<^10>, and the modular behavior
+requires some extra syntax.
+
=for vim:set expandtab sw=4:

TSa

unread,
Jan 30, 2007, 2:25:37 PM1/30/07
to perl6-l...@perl.org
HaloO,

la...@cvs.develooper.com wrote:
> + The lower


> +right corner of a two dimesional array is C<@array[*-1, *-1]>.

That should read @array[*-1; *-1], or not?
--

Larry Wall

unread,
Jan 30, 2007, 2:36:26 PM1/30/07
to perl6-l...@perl.org
On Tue, Jan 30, 2007 at 08:25:37PM +0100, TSa wrote:
: HaloO,

Right you are. Though that makes me wonder if a multidimensional
Whatever (**) will work to mean the same thing in "whatever" dimensions
there are:

@array[**-1]

No clue if that every would be useful to anyone...

Larry

David Green

unread,
Feb 5, 2007, 7:28:10 PM2/5/07
to perl6-l...@perl.org
On 1/30/07, la...@cvs.perl.org wrote in "[svn:perl6-synopsis] r13549
- doc/trunk/design/syn":

>+It has become the custom to use negative subscripts to indicate counting
>+from the end of an array. This is still supported, but only for unshaped
>+arrays:
>+For shaped arrays you must explicitly refer to the current endpoint
>+using C<*>, the C<Whatever> object:

Bringing us back to the discussion of ordinals from a few years ago...

On 9/6/04, Larry Wall wrote in "Re: Synopsis 9 draft 1":
>Another possibility is that .[] always forces the "normal" view of
>an array as 0-based, and if you want non-0-based arrays you have to
>use the .{} interface instead, on the assumption that strange
>subscripts
>are more like hash keys than ranges of integers. Certainly if you
>have a sparse array with keys like 1,2,4,8,16,32... you have a
>situation that's more like a hash than an array. A sparse array
>might not even give you the .[] interace. The presence of a .[]
>interface might signal the ability to process contigous ranges, even
>if those ranges are offset from the .{} range.
>
>Such an approach would have the benefit that a module could simply
>treat all its arrays as 0-based .[] arrays, and if you happened to
>pass a non-0-based .{} array in, it would still work, albeit with
>0-based indexes instead of whatever shape the .{} interface uses.

I don't think anything came of that, but the more I think about it,
the more I like it. Sparse/negative/etc. array indices really are
more like hash-keys than ordinals, so why don't we go ahead and have
two different ways to look up elements from arrays and hashes?

Also, this would solve a problem I've been wondering about with
"funny" shapes being lexically scoped. From S09:
>You can pretend you're programming in Fortran, or awk:
> my int @ints (1..4, 1..2); # two dimensions, @ints[1..4; 1..2]
>
>Note that this only influences your view of the array in the current
>lexical scope, not the actual shape of the array. If you pass this
>array to another module, it will see it as having a shape of
>(0..3,0..1) unless it also declares a variable to view it
>differently.

However, what if you pass the funny array along with a (funny) index?
E.g. our @flavours (1..32);
my $favourite = get_fave(@flavours); #returns index of selected flavour
warn "Sorry, all out of @flavours[$favourite]!"
unless in_stock(@flavours, $favourite);

Which means that you'd be checking for the wrong thing to be in
stock. (Actually, you'd also get the wrong index back from
get_fave(), so in this limited example, the two errors would probably
cancel each other out, but the warning message will print the wrong
flavour because it's using the shifted index.)

Of course, thinking of arrays as numbered consecutively from 0 to n
will probably result in speaking P6 with a P5 accent: better to "for
[each]" over an array rather than loop across index numbers. If you
needed to use the index values, there was no alternative in P5 (or C,
etc.), but now we can use @foo.keys or .kv, and get the actual
indices even when the array is sparse, or uses negative subscripts.

But there will still be a need to traverse arrays ordinally, so I
think reserving [] lookups for this purpose is a good idea. Then
it's always clear whether you're using the "funny" (i.e. {}) keys or
the "old-fashioned" (i.e. []) ordinals. And negative subscripts can
always count backwards inside [] (and just be actual negative keys
inside {}).

Then we wouldn't need * to count backwards, although it's still
useful to allow us to count past the end of an array. There are all
sorts of variations on this scheme, such as whether * is the last
element or the one after that, etc., or whether 0 should be the first
element or the last, and so on.

(And of course, if arrays can be indexed with {}, then hashes can be
indexed with [] -- dunno if there's any point for ordinary hashes,
but it certainly could be useful with ordered ones.)


-David

David Green

unread,
Feb 5, 2007, 7:42:38 PM2/5/07
to perl6-l...@perl.org
On 2/5/07, David Green wrote:
>Then we wouldn't need * to count backwards, although it's still
>useful to allow us to count past the end of an array. There are all
>sorts of variations on this scheme, such as whether * is the last
>element or the one after that, etc., or whether 0 should be the
>first element or the last, and so on.

In some ways, I like not having a [0] index at all: programmers may
be used to counting from zero, but normal humans start with first,
second, third, ... third last, second last, ["first"] last, so it
would make sense to count:
@foo=@foo[1, 2, 3, ..., -3, -2, -1]

And then to count past the ends, something like:
[..., -*-2, -*-1, -*, 1, 2, 3, ..., -3, -2, -1, +*, *+1, *2, ...]

Or since * stands for everything, maybe that should be ..., *-2, *-1,
* , *+1, *+2, ...?
The thing I like best about this option is that it most clearly
preserves the notion of "*" as "everything"; *-1 is the element
before everything, and *+1 is the element after everything else.


If there is a way to work "modulated" (cyclic/wrap-around) arrays
into this, then we'd want to have a zero in there somewhere, although
it still wouldn't have to be first; instead count first, second,
third, ..., last but two, last but one, last:
[1, 2, 3, ..., -2, -1, 0]

(So, for a mod-4 array,
@foo=@foo[1,2,3,4]=@foo[5,6,7,8]=@foo[-3,-2,-1,0] etc.?)


Yet another way (that avoids distinct +* and -*) is:
[..., -2,-1] @foo[0, 1, 2, ..., *-2, *-1] [+*, *+1, *+2, ...]
(or [..., -1, 0] @foo[1, 2, 3, ..., *-1, +*] [*+1, *+2, ...] or something.)

Then *+/-n always refers to the end point, and we can count
continuously across the front end of an array or the back.


-David

TSa

unread,
Feb 6, 2007, 6:34:11 AM2/6/07
to perl6-l...@perl.org
HaloO,

David Green wrote:
> Also, this would solve a problem I've been wondering about with "funny"

> shapes being lexically scoped. [..]


> However, what if you pass the funny array along with a (funny) index?
> E.g. our @flavours (1..32);
> my $favourite = get_fave(@flavours); #returns index of selected
> flavour
> warn "Sorry, all out of @flavours[$favourite]!"
> unless in_stock(@flavours, $favourite);
>
> Which means that you'd be checking for the wrong thing to be in stock.
> (Actually, you'd also get the wrong index back from get_fave(), so in
> this limited example, the two errors would probably cancel each other
> out, but the warning message will print the wrong flavour because it's
> using the shifted index.)

It's interesting to get the signature for this &get_fave routine.
As stated it should be :(@a --> Int where {$_ ~~ @a.begin..^@a.end}).
The implementation of &get_favo has to be generic with respect to
the array shape otherwise a type error occurs when e.g. the shape
is (-5..-1) and the body of &get_favo is coded in terms of (0..4).

And I wonder how this generic index handling can be done by means
of * dwimmery along the lines of

sub get_favo (@a --> Int where {$_ ~~ @a.begin..^@a.end})
{
my $idx = *+0; # how is this connected to @a?

while check_favo(@a[$idx]) and $idx < *-0 # same as @a.end?
{
$idx++;
}
return $idx;
}

BTW, is the where clause in the signature still seeing the outside
shape? Or does one have to say something like @a.OUTER::begin to
get at it because the @a of the sub always has got shape (0..^+@a)?


Regards, TSa.
--

Blair Sutton

unread,
Feb 6, 2007, 10:21:07 AM2/6/07
to perl6-l...@perl.org
David Green wrote:
> On 2/5/07, David Green wrote:
>> Then we wouldn't need * to count backwards, although it's still
>> useful to allow us to count past the end of an array. There are all
>> sorts of variations on this scheme, such as whether * is the last
>> element or the one after that, etc., or whether 0 should be the first
>> element or the last, and so on.
>
> In some ways, I like not having a [0] index at all: programmers may be
> used to counting from zero, but normal humans start with first,
> second, third, ... third last, second last,...
My feelings are Perl 6 should stick to 0 being the index of the first
element of a list. Otherwise we might alienate programmers from P5 and
nearly every other language. Couldn't the first array index be adjusted
by adding a user defined Parrot grammar definition that applies the
transformation +1 inside [] operators instead; maybe this could be
accessible via a Perl "use" pragma.

Smylers

unread,
Feb 6, 2007, 11:41:30 AM2/6/07
to perl6-l...@perl.org
Blair Sutton writes:

> David Green wrote:
>
> > In some ways, I like not having a [0] index at all: programmers may
> > be used to counting from zero, but normal humans start with first,
> > second, third, ... third last, second last,...
>
> My feelings are Perl 6 should stick to 0 being the index of the first
> element of a list. Otherwise we might alienate programmers from P5 and
> nearly every other language. Couldn't the first array index be
> adjusted by adding a user defined Parrot grammar definition that
> applies the transformation +1 inside [] operators instead; maybe this
> could be accessible via a Perl "use" pragma.

Hmmm, a pragma's a bit heavyweight for this; how about being able to set
this with a special global variable -- that sure sounds handy ...

Smylers

Jonathan Scott Duff

unread,
Feb 6, 2007, 12:14:12 PM2/6/07
to Smylers, perl6-l...@perl.org

I can't quite tell how serious you are :-)

I can't see Perl 6 changing the default starting index of arrays to be
anything other than 0 because that meme is so pervasive (look at where
substr() starts, and how we now have $0, etc.). But I can see the need for
a pragma to help out the Pascal or Fortran programmers start all of their
arrays at something other than 0. And I can see the need for a modifier so
that an individual array can start at an index other that 0.

just registering my tuppence,

-Scott
--
Jonathan Scott Duff
perl...@gmail.com

Rafael Garcia-Suarez

unread,
Feb 7, 2007, 4:08:47 AM2/7/07
to perl6-l...@perl.org
Smylers wrote in perl.perl6.language :

> Hmmm, a pragma's a bit heavyweight for this; how about being able to set
> this with a special global variable -- that sure sounds handy ...

Actually, in perl 5, $[ *is* a pragma... :)

--
Grepping the source is good for the soul. -- the perldebguts manpage

Blair Sutton

unread,
Feb 8, 2007, 3:42:25 PM2/8/07
to perl6-l...@perl.org
Rafael Garcia-Suarez wrote:
> Smylers wrote in perl.perl6.language :
>
>> Hmmm, a pragma's a bit heavyweight for this; how about being able to set
>> this with a special global variable -- that sure sounds handy ...
>>
>
> Actually, in perl 5, $[ *is* a pragma... :)
>
>
A feature I have never felt the need to use but useful in any case. I
suspect there is a way in Perl 6 to specify Parrot grammar directives
that could adjust this behaviour? Maybe even allow you to use named
numbers as well as digits, i.e. @a[zero], @b[twelve]... :)

Blair Sutton

unread,
Feb 8, 2007, 3:41:17 PM2/8/07
to perl6-language@perl.org >> perl6language
Rafael Garcia-Suarez wrote:
> Smylers wrote in perl.perl6.language :
>
>> Hmmm, a pragma's a bit heavyweight for this; how about being able to set
>> this with a special global variable -- that sure sounds handy ...
>>
>
> Actually, in perl 5, $[ *is* a pragma... :)
>
>

Smylers

unread,
Feb 6, 2007, 3:49:16 PM2/6/07
to perl6-l...@perl.org
Jonathan Scott Duff writes:

> On 2/6/07, Smylers <Smy...@stripey.com> wrote:
>
> > Blair Sutton writes:
> >
> > > David Green wrote:
> > >
> > > > In some ways, I like not having a [0] index at all: programmers
> > > > may be used to counting from zero, but normal humans start with
> > > > first, second, third, ... third last, second last,...
> > >
> > > My feelings are Perl 6 should stick to 0 being the index of the
> > > first element of a list. Otherwise we might alienate programmers
> > > from P5 and nearly every other language. Couldn't the first array
> > > index be adjusted by adding a user defined Parrot grammar
> > > definition that applies the transformation +1 inside [] operators
> > > instead; maybe this could be accessible via a Perl "use" pragma.
> >
> > Hmmm, a pragma's a bit heavyweight for this; how about being able to
> > set this with a special global variable -- that sure sounds handy
> > ...
>
> I can't quite tell how serious you are :-)

I was being completely serious in my attempt to remind folk of C<$[> in
Perl 5, how much it is despised, and that it is a mistake that Perl 6
won't be repeating.

> ... I can see the need for a pragma to help out the Pascal or Fortran


> programmers start all of their arrays at something other than 0.

Those sort of crutches in programming languages (let's help folk who
know some other language -- meaning they end up programming in some
hybrid of the two languages) often turn out to be a mistake. Think of
Pascal programmers #define-ing begin and end as { and } in C, or
WordBasic being 'localized' into French, or C<use English> in Perl 5.

Part of this is cos they are mostly unnecessary: there are so many
fundamental and much deeper differences between Pascal and Perl that any
Pascal programmer who's managed to learn about and cope with all the
weird and wonderful things that Perl offers isn't going to struggle with
the relatively superficial difference in array subscripts.

> And I can see the need for a modifier so that an individual array can
> start at an index other that 0.

Isn't that something shaped arrays can already do?

Smylers

Jonathan Scott Duff

unread,
Feb 14, 2007, 9:31:55 AM2/14/07
to Smylers, perl6-l...@perl.org
On 2/6/07, Smylers <Smy...@stripey.com > wrote:
>
> Jonathan Scott Duff writes:
>
> > ... I can see the need for a pragma to help out the Pascal or Fortran
> > programmers start all of their arrays at something other than 0.
>
> Those sort of crutches in programming languages (let's help folk who
> know some other language -- meaning they end up programming in some
> hybrid of the two languages) often turn out to be a mistake. Think of
> Pascal programmers #define-ing begin and end as { and } in C, or
> WordBasic being 'localized' into French, or C<use English> in Perl 5.


Sure, but I wouldn't kick out another man's crutches just because I
think he doesn't need them. Nor would I deny a man some crutches
because I have a philosophical objection to his limp.


Part of this is cos they are mostly unnecessary: there are so many
> fundamental and much deeper differences between Pascal and Perl that any
> Pascal programmer who's managed to learn about and cope with all the
> weird and wonderful things that Perl offers isn't going to struggle with
> the relatively superficial difference in array subscripts.


If you say so. I've seen code that uses perl to get it's job done but is
clearly written in a very C-ish way. Not *needing* to learn about and cope
with all the weird and wonderful things that Perl offers is one of its
strengths IMHO.

0 new messages