[Python-ideas] Where did we go wrong with negative stride?

Nick Coghlan ncoghlan at gmail.com
Mon Oct 28 23:29:35 CET 2013


On 29 Oct 2013 06:21, "Oscar Benjamin" <oscar.j.benjamin at gmail.com> wrote:
>
> On 28 October 2013 15:04, Brett Cannon <brett at python.org> wrote:
> >
> > On Mon, Oct 28, 2013 at 10:49 AM, Oscar Benjamin
> > <oscar.j.benjamin at gmail.com> wrote:
> >>
> >> On 28 October 2013 13:57, Brett Cannon <brett at python.org> wrote:
> >>
> >> I think that the numpy mailing lists should be consulted before any
> >> decisions are made. As Antoine says: if you've never noticed this
> >> behaviour before then it obviously doesn't matter to you that much so
> >> why the rush to deprecate it?
> >
> > I'm not saying not to talk to them, but I also don't think we should
> > necessarily not change it because no one uses it either. If it's wide
spread
> > then sure, we just live with it. It's always a balancing act of fixing
for
> > future code vs. pain of current code. I'm just saying we shouldn't
dismiss
> > changing this out of hand because you are so far the only person who has
> > relied on this.
>
> Anyone who has used negative strides and non-default start/stop is
> relying on it. It has been a core language feature since long before I
> started using Python.
>
> Also I'm not the only person to point out that a more common problem
> is with wraparound when doing something like a[:n]. That is a more
> significant problem with slicing and I don't understand why the
> emphasis here is all on the negative strides rather then negative
> indexing. Using negative indices to mean "from the end" is a mistake
> and it leads to things like this:
>
> >>> a = 'abcdefg'
> >>> for n in reversed(range(7)):
> ...     print(n, a[:-n])
> ...
> 6 a
> 5 ab
> 4 abc
> 3 abcd
> 2 abcde
> 1 abcdef
> 0
>
> You can do something like a[:-n or None] to correctly handle zero but
> that still does the wrong thing when n is negative.
>
> Also why do you get an error when your index goes off one end of the
> array but not when it goes off the other?
>
> >>> a[len(a)]
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> IndexError: string index out of range
> >>> a[-1]
> 'g'
>
> I have never been in a situation where I was writing code and didn't
> know whether I wanted to slice/index from the end or the beginning at
> coding time. I would much rather that a[-1] be an error and have an
> explicit syntax for indexing from the end.
>
> I have never found this wraparound to be useful and I think that if
> there is a proposal to change slicing in a backward incompatible way
> then it should be to something that is significantly better by solving
> these real problems. I have often had bugs or been forced to write
> awkward code because of these. The negative slicing indices may be a
> bit harder to reason about but it has never actually caused me any
> problems.
>
> Something like the matlab/pike syntax would fix these problems as well
> as making it possible to use the same indices for negative stride
> slices. That would be worth a deprecation process in my opinion. The
> specific suggestion so far does not have enough of an advantage to
> justify breaking anyone's code IMO.
>
> > As for the rush, it's because 3.4b1 is approaching and if this slips to
3.5
> > that's 1.5 years of deprecation time lost for something that doesn't
have a
> > syntactic break to help you discover the change in semantics.
> >>
> >> > +1 on doing a deprecation in 3.4.
> >>
> >> -1 on any deprecation without a clear plan for a better syntax. Simply
> >> changing the semantics of the current syntax would bring in who knows
> >> how many off-by-one errors for virtually no benefit.
> >
> > The deprecation would be in there from now until Python 4 so it
wouldn't be
> > sudden (remember that we are on a roughly 18 month release cycle, so if
this
> > went into 3.4 that's 7.5 years until this changes in Python 4). And
there's
> > already a future-compatible way to change your code to get the same
results
> > in the end that just require more explicit steps/code.
>
> This argument would be more persuasive if you said: "the new better
> syntax that solves many of the slicing problems will be introduced
> *now*, and the old style/syntax will be deprecated later".

Indeed. I like Terry's proposed semantics, so if we can give that a new
syntax, we can just give range and slice appropriate "reverse=False"
keyword arguments like sorted and list.sort, and never have to deprecate
negative strides (although negative strides would be disallowed when
reverse=True).

For example:

s[i:j:k] - normal forward slice
s[i:j:<<k] - reversed slice (with i and j as left/right rather than
start/stop)

Reversing with unit stride could be:
s[i:j:<<]

When reverse=True, start, stop and step for the range or slice would be
calculated as follows:

start = len(s)-1 if j is None else j-1
stop = -1 if i is None else i-1
step = -k

It doesn't solve the -j vs len(s)-j problem for the end index, but I think
it's still more intuitive for the reasons Tim and Terry gave.

Cheers,
Nick.

>
>
> Oscar
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20131029/cfac83f7/attachment.html>


More information about the Python-ideas mailing list