... [Tim]

"Cut between positions" in my view has nothing to do with the stride. It's used to determine the portion of the sequence _to which_ the stride applies. From that portion, we take the first element, the first + |stride|'th element, the first + |stride|*2'th element, and so on. Finally, if stride < 0, we reverse that sequence. That's the proposal. It's simple and uniform.

[Steven D'Aprano]

That's quite a nice model, and I can't really say I dislike it. But it fails to address your stated complaint about the current behaviour, namely that it forces the user to think about array indexing instead of cutting between elements. No matter what we do, we still have to think about array indexes.

As a Python implementer, _I_ do, but not as a user. As Guido noted, under the proposal we have: s[i:j:k] == s[i:j][::k] That should (finally?) make it crystal clear that applying the stride has nothing directly to do with the indices of the selected elements in the original sequence (`s`). In the RHS's "[::k]", all knowledge of s's indices has been lost. If _you_ want to think of it in terms of indices into `s`, that's fine, and the implementation obviously needs to index into `s` to produce the result, but a user can just think "OK! start at the start and take every k'th element thereafter". As in, e.g., the sieve of Eratosthenes: "search right until you find the first integer not yet crossed out. Call it p. Then cross out every p'th integer following. Repeat." There's no reference made to "indices" there, and none needed in the mental model. An implementation using an array or list will need to know the index of p, but that's it. If that index is `i`, then, e.g., array_or_list[i+p: :p] = [False] * len(range(i+p, len(array_or_list), p)) faithfully translates the rest. [...]

In other words, you want negative strides to just mean "reverse the slice"

If they're given a ;meaning at all.

Is this a serious proposal to prohibit negative slices?

No. I do wonder whether negative strides have been "an attractive nuisance" overall, but guess they'd be more "attractive" than "nuisance" under the proposal. [...]

One consequence of this proposed change is that the <start> parameter is no longer always the first element returned. Sometimes <start> will be last rather than first. That disturbs me.

? <start> is always the first element of the subsequence to which the stride is applied. If the stride is negative, then yes, of course the first element of the source subsequence would be the last element of the returned subsequence.

Right. And that's exactly what I dislike about the proposal.

OK. Then use a positive stride ;-)

I have a couple of range-like or slice-like functions which take start/stop/stride arguments. I think I'll modify them to have your suggested semantics and see how well they work in practice.

Good idea! I made only one real use of non-trivial negative strides, that I can recall, in the last year: # nw index is n-1+i-j # in row i, that's n-1+i thru n-1+i-(n-1) = i # the leftmost is irrelevant, so n-1+i-1 = n-2+i thru i # ne index is i+j # in row i, that's i thru i+n-1 # the rightmost is irrelevant, so i thru i+n-2 assert nw[n-1+i] == 0 assert ne[i+n-1] == 0 codes = [0] * (3*n - 2) codes[0::3] = up codes[1::3] = ne[i: n-1+i] codes[2::3] = nw[n-2+i: i-1: -1] # here That was excruciating to get right. Curiously, the required `ne` and 'nw` index sets turned out to be exactly the same, but _end up_ looking different in that code because of the extra fiddling needed to deal with that the required 'nw` index _sequence_ (as opposed to the index set) is the reverse of the required `ne` index sequence. Under the proposal, the last line would be written: codes[2::3] = nw[i: n-1+i: -1] instead, making it obvious at a glance that the the 'nw` index sequence is the reverse of the `ne` index sequence. And that's all the empirical proof I need - LOL ;-)

...