Slice syntax

3,528 views
Skip to first unread message

Kim

unread,
Nov 14, 2009, 6:06:51 PM11/14/09
to golan...@googlegroups.com
I've been playing with slices. In perl a slice such as a[ 0..2] would represent elements a[ 0 ], a[ 1 ], a[ 2 ].
If I not mistaken, the slice a[0:2] in go represents a[ 0 ], a[ 1 ]

The second value is not a length, nor is it the last index value, what is the reasoning behind this meaning,
the perl approach seems more logical? Why is the second value a value that is not a valid index in the array??

Cheers,
Kim

manatlan

unread,
Nov 14, 2009, 6:12:37 PM11/14/09
to golang-nuts
it's perfect for me, it's like python ;-)

the only bad things about slice in "go", is the unsigned int for
bounds.
letting write a[1:-3], or things like a[2:] or a[:-4] would be really
perfect

Helmar

unread,
Nov 14, 2009, 6:23:23 PM11/14/09
to golang-nuts
Oh, no. Not Perl. Perl has nice mechanisms about how to index things.
In Go/Issue9 it is completely obvious that what you do as foo in foofoo
[x:foo] is the upper border that never will be accessed. Perl has
something nice (and I do not know why nobody refers to it) that means
that negative indices to arrays (or in this case slices) are meant to
be taken from the end of the entity to be accessed. That means [-1] is
last element. A very comfortable solution imho. "Go" did go to another
direction in this particular topic. I'm really sad about that at the
one hand. Other hand says it's something that forces better sources
where you can read in clean what happens. But well, even that Go/
Issue9 has some parts of syntax that makes Perl-inventors having
headache why they did not invent this first (say checking if something
is in a "map").

-Helmar

Rob 'Commander' Pike

unread,
Nov 14, 2009, 6:23:57 PM11/14/09
to manatlan, golang-nuts

On Nov 14, 2009, at 3:12 PM, manatlan wrote:

> it's perfect for me, it's like python ;-)
>
> the only bad things about slice in "go", is the unsigned int for
> bounds.
> letting write a[1:-3], or things like a[2:] or a[:-4] would be really
> perfect

This was left out deliberately because the slice expression s[i:j] can
suddenly misbehave, silently, if j goes negative. In fact there was
a nasty bug in rietveld a while back for just this reason.

Indices must be non-negative.

-rob

manatlan

unread,
Nov 14, 2009, 6:30:45 PM11/14/09
to golang-nuts
I understand ...

and letting write a[2:] (which is like a[2:len(a)] ), not an option ?
(or perhaps just the idiomatic a[-1] for the last byte ?)

loftylurker

unread,
Nov 15, 2009, 8:10:28 AM11/15/09
to golang-nuts
Ahhh, it all becomes clear. I knew there had to be some reason for it.
So the whole purpose of this approach is to deal with code that
defines empty slice sections and in that case then leaves the second
index non-negative because of bad things that happen if it does. A
second reason may well be the influence that python has had on it's
design if that is the way that python does it, considering the python
designer works at Google as well. Perhaps then, it would be better to
aim that question at the python designers.

At the end of the day however, it does appear to be a decision based
on some underlying implementation reasons rather than by it's apparent
interpretation. Unless the designers feel that it interprets more
logical the go way as well of course. I can conceive that it
eliminates one add or subtract operation.

Cheers,
Kim

loftylurker

unread,
Nov 15, 2009, 7:29:13 PM11/15/09
to golang-nuts
Actually, it's no big deal so long as you know that you have to
specify the end index as one past that which you wish to go to. I
searched far and wide in the documentation for the specification as to
what the second index actually meant. Maybe I missed it somewhere but
it appears as if it's not actually mentioned anywhere. Not in the
effective go acticle or the language specification. My apologies if
I've simply overlooked it.

Kim

Robert Griesemer

unread,
Nov 15, 2009, 7:45:02 PM11/15/09
to loftylurker, golang-nuts
The language specification states clearly what the slice indices mean:


"Strings, arrays, and slices can be sliced to construct substrings or descriptors of subarrays. The index expressions in the slice select which elements appear in the result. The result has indexes starting at 0 and length equal to the difference in the index values in the slice."

and:

"The slice length must not be negative. For arrays or strings, the indexes lo and hi must satisfy 0 <= lo <= hi <= length; for slices, the upper bound is the capacity rather than the length."

- gri

Rémy Oudompheng

unread,
Mar 16, 2013, 7:40:37 AM3/16/13
to david....@gmail.com, golan...@googlegroups.com, loftylurker, g...@golang.org
On 2013/3/16 <david....@gmail.com>:
> in python, s[-3:] as shorthand for s[len(s)-3:] is clear and easy
> if the second one fails, the first one does too
> you're using python syntax because it does this well...
>
> this is obviously an ancient thread, but I'm trying to learn go and this
> thread is referenced as explaining the "reason for not allowing negative
> indices". I don't see a reason other than "because that's what the spec
> says". so please excuse what is mostly me whining so I can move on and get
> back to the tutorial :)

len(s[i:]) == len(s) - i is false in Python, it is not false in Go.
Assigning a single meaning to an expression rather than multiple
conditional meanings avoid mistakes.

Go is not about making code shorter, but making it more correct and
less error-prone: that's why you may feel it's more repetitive or
boring, and but it makes the process of programming much more
straightforward.
You will still find many elegant constructions in Go anyway.

Rémy.

Jan Mercl

unread,
Mar 16, 2013, 7:48:24 AM3/16/13
to david....@gmail.com, golang-nuts, loftylurker, g...@golang.org
On Sat, Mar 16, 2013 at 6:43 AM, <david....@gmail.com> wrote:
> in python, s[-3:] as shorthand for s[len(s)-3:] is clear and easy

Maybe too easy compared to those few character more to be written in
the explicit case. Off by one errors are common. Currently if some
index expression has a bug and instead of value '0' it yields '-1',
the program will panic. With the "negative indices has other meaning"
trick, the program will silently continue working with the last
instead of the first element of an array/slice.

-j

Rémy Oudompheng

unread,
Mar 17, 2013, 1:03:07 AM3/17/13
to david....@gmail.com, Robert Griesemer, golang-nuts, loftylurker


On 17 Mar 2013 05:07, <david....@gmail.com> wrote:
>
> 2 responses to a 4 year stale thread at 5am on a weekend... impressive, thanks!
>
> Remy, it took me a while to understand what you were saying (which may have been proving your point).  I think you're incorrect though
>
> python:
> s, i = range(10), 3
> print len(s[i:]) == len(s) - i   # prints: True
>
> go:
> s, i := make([]int, 10), 3
> for j := range s {
> s[j] = j
> }
> fmt.Println(len(s[i:]) == len(s) - i) //prints: true
>

Try with i=-3. If you don't like to say it is false, let's say it is not true.

Rémy.

David Tudury

unread,
Mar 17, 2013, 2:28:27 AM3/17/13
to Rémy Oudompheng, Robert Griesemer, golang-nuts, loftylurker
Remy,  thanks for the follow up.  If I try negative indices, it crashes.  Go doesn't swing that way.  The question was whether go could do something useful there (like python).  Jan said that crashing is something useful (which I'm still trying to come to terms with) :)

-- 
David Tudury
+1.510.224.5556

Kevin Gillette

unread,
Mar 17, 2013, 2:42:16 AM3/17/13
to golan...@googlegroups.com
The point is that ints are a continuous range with consistent properties, but python grafts inconsistency onto the integer range in the name of convenience. Go is no less capable (you can still refer to indices relative to the end because you can use len(s) as an expression), but is less expressive in this area. Go's stance is to disfavor artificial complexity. The exemplification of the other extreme is something like enterprise java, which extremely artificial and extremely complex, but presumably is very convenient for anyone who can manage to cut their way past the magic and actually manage to learn the framework.

Russ Cox

unread,
Mar 18, 2013, 10:19:06 AM3/18/13
to david....@gmail.com, golang-nuts, loftylurker, Robert Griesemer
In the text you quoted:

Nate Finch

unread,
Mar 18, 2013, 2:55:43 PM3/18/13
to golan...@googlegroups.com, david....@gmail.com, loftylurker, Robert Griesemer
The explanation that got to me last time this came up was like this:
Most slice indices tend to live near 0. Since they can be calculated based on variables, a tiny error in calculation can send a positive number into the negatives... which has wildly different results.

For example:

Say you have a slice of 2048 bytes. 
You want to slice off the first 3 bytes, so you're slicing from 
0 -> 3
Now, if you're calculating the value of 3, and you happen to be off by 4 (because of a bug during bit shifting or something), you might actually be slicing
0 -> -1

Suddenly, instead of having a slice of 3 bytes, you have a slice of 2047 bytes. That's 3 orders of magnitude difference, all because you were off by 4 on one number. And your code might not even fail now, you'll just have WAY more data than you thought... or if it does fail at some point, it'll be further down in the code, and figuring out why it's doing this crazy thing will be really hard. 

Compare, instead, that when this happens, you get a panic that says -1 is an invalid index.... the error is produced right at the point where the error is introduced. You'll know exactly where to debug, and it should be pretty obvious what happened with very little effort.

...all that to save a few characters, so you can type a[0:-3] instead of a[0:len(a)-3] ?  Not worth it.

david tudury

unread,
Mar 18, 2013, 5:24:36 PM3/18/13
to golan...@googlegroups.com, david....@gmail.com, loftylurker, Robert Griesemer
for the record, I've made peace with some little annoyances in exchange for the other go features

obviously, one of the languages I'm coming from is python.  The go language authors chose to use a standard I am familiar with to mean something fairly different (in addition to allowing negative indices, python returns a copy while go returns a pointer).  My experience is that even the standards I think I recognize are strange and inconsistent relative to my expectation.  Please hear my frustration as the frustration of someone trying to learn a new language, not someone too lazy to type "len(variableName)".

Nate, by that logic go should get rid of uint too
var v uint
v -= 1
fmt.Println(v) //4294967295
it's a dumb example...  the point is: I'm not sure off-by-one errors so common and so difficult to debug that it is worth it... my projects are probably all too small
(too flamey?  sorry, I really really appreciate the responses, I'm just having a hard time letting this go for whatever reason.  Assuming no one names me in a response, I promise to leave this thread alone :)

Dan Kortschak

unread,
Mar 18, 2013, 5:37:34 PM3/18/13
to golan...@googlegroups.com
Which is why the default type for integer values and the type returned by a range expression is int and not uint.
Reply all
Reply to author
Forward
0 new messages