[swift-evolution] Proposal: Python's indexing and slicing

Kevin Ballard kevin at sb.org
Sat Dec 19 22:52:23 CST 2015

On Fri, Dec 18, 2015, at 02:39 PM, Dave Abrahams via swift-evolution wrote:
> Yes, we already have facilities to do most of what Python can do here,
> but one major problem IMO is that the “language” of slicing is so non-
> uniform: we have [a..<b], dropFirst, dropLast, prefix, and suffix.
> Introducing “$” for this purpose could make it all hang together and
> also eliminate the “why does it have to be so hard to look at the 2nd
> character of a string?!” problem.  That is, use the identifier “$”
> (yes, that’s an identifier in Swift) to denote the beginning-or-end of
> a collection.  Thus,
> c[c.startIndex.advancedBy(3)] =>c[$+3]        // Python: c[3]  c[c.endIndex.advancedBy(-
> 3)] =>c[$-3]        // Python: c[-3]
> c.dropFirst(3)  =>c[$+3...]     // Python: c[3:]  c.dropLast(3) =>c[..<$-
> 3]     // Python: c[:-3]  c.prefix(3) =>c[..<$+3]     // Python: c[:3]
> c.suffix(3) => c[$-3...]     // Python: c[-3:]
> It even has the nice connotation that, “this might be a little more
> expen$ive than plain indexing” (which it might, for non-random-access
> collections).  I think the syntax is still a bit heavy, not least
> because of “..<“ and “...”, but the direction has potential.
> I haven’t had the time to really experiment with a design like this;
> the community might be able to help by prototyping and using some
> alternatives.  You can do all of this outside the standard library
> with extensions.

Interesting idea.

One downside is it masks potentially O(N) operations
(ForwardIndex.advancedBy()) behind the + operator, which is typically
assumed to be an O(1) operation. Alos, the $+3 syntax suggests that it
requires there to be at least 3 elements in the sequence, but
prefix()/suffix()/dropFirst/etc. all take maximum counts, so they
operate on sequences of fewer elements.

There's also some confusion with using $ for both start and end. What
if I say c[$..<$]? We'd have to infer from position that the first $ is
the start and the second $ is the end, but then what about
c[$+n..<$+m]? We can't treat the usage of + as meaning "from start"
because the argument might be negative. And if we use the overall sign
of the operation/argument together, then the expression `$+n` could
mean from start or from end, which comes right back to the problem with
Python syntax.

I think Jacob's idea has some promise though:

c[c.startIndex.advancedBy(3)] => c[fromStart: 3]
c[c.endIndex.advancedBy(-3)] => c[fromEnd: 3]

But naming the slice operations is a little trickier. We could actually
just go ahead and re-use the existing method names for those:

c.dropFirst(3) => c[dropFirst: 3]
c.dropLast(3) => c[dropLast: 3]
c.prefix(3) => c[prefix: 3]
c.suffix(3) => c[suffix: 3]

That's not so compelling, since we already have the methods, but I
suppose it makes sense if you want to try and make all slice-producing
methods use subscript syntax (which I have mixed feelings about). But
the [fromStart:] and [fromEnd:] subscripts seem useful.

-Kevin Ballard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151219/a482a386/attachment.html>

More information about the swift-evolution mailing list