> Am 15.10.2017 um 21:22 schrieb Xiaodi Wu <xiaodi...@gmail.com>: > > > On Sun, Oct 15, 2017 at 14:14 Thorsten Seitz <tseit...@icloud.com> wrote: >>> Am 15.10.2017 um 10:38 schrieb Xiaodi Wu via swift-evolution >>> <swift-evolution@swift.org>: >>> >>>> On Sun, Oct 15, 2017 at 2:29 AM, Kevin Nattinger <sw...@nattinger.net> >>>> wrote: >>>> >>>>> On Oct 14, 2017, at 7:54 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote: >>>>> >>>>> On Sat, Oct 14, 2017 at 6:17 PM, Kevin Nattinger <sw...@nattinger.net> >>>>> wrote: >>>>>>>>> […] >>>>>>>>> * A Swift `Sequence` is, to put it simplistically, a thing that can >>>>>>>>> be iterated over in a `for...in` loop. If it would make you happy, >>>>>>>>> for the rest of the discussion, let's suppose we called the protocol >>>>>>>>> `ForLoopable` instead of `Sequence`. >>>>>>>> >>>>>>>> ForLoopable is so ugly. Since we’re just iterating over the elements, >>>>>>>> how about, oh, say, `Iterable`? Hey, that looks familiar. >>>>>>> >>>>>>> I'm not trying to bikeshed the name of `Sequence`. I'm picking an >>>>>>> intentionally unwieldy name for the purposes of discussing the >>>>>>> semantics of this particular protocol. The point is that the underlying >>>>>>> issue has nothing to do with the name; it can be `Iterable` or it can >>>>>>> be `SpongeBob` for all I care. >>>>>> >>>>>> I’m not trying to bikeshed the name either, The underlying issue is that >>>>>> (what is currently) Sequence actually encompasses two separate >>>>>> functionalities, and those functionalities need to be separated with >>>>>> their separate semantic requirements documented. “Sequence: Iterable,” >>>>>> “OrderedSequence: Sequence,” “SpongeBob: ForLoopable,” the names are >>>>>> 100% irrelevant at this point; what’s important is that one is not >>>>>> necessarily ordered and the other guarantees an order. >>>>> >>>>> What are the "two separate functionalities”? >>>> >>>> Iteration, with convenience methods that don’t imply or rely on an order >>>> that may not be there; and convenience methods applicable to sequences >>>> that do have an intrinsic order. >>> >>> Sets, as a mathematical concept, have no intrinsic order. However, >>> instances of `Set`, which can be iterated over, *do* have at least one >>> order which can be said to be intrinsic in the following sense: as long as >>> iteration is possible, no API design can prevent that order from being >>> observed and associated with the instance. Put another way, if you can use >>> an instance of a type in a for...in loop, intrinsic to that functionality >>> is a publicly visible order. >> >> I disagree. Sets are value types, therefore two instances of `Set` are equal >> if they contain the same elements. An intrinsic order should therefore only >> depend on the elements contained and should be the same for two instances of >> `Set` which are equal. >> This is not the case, though, as you can easily check in a playground by >> looking at Set([1,2,3,4,5,6]) and Set([6,5,4,3,2,1]) which represent the >> same value and are equal but do *not* have the same order. >> >> >>> >>>> >>>>> All the extension methods on Sequence are ways of spelling things that >>>>> you can write in a few lines of code using a `for...in` loop; they're in >>>>> the stdlib to allow a more functional style which some prefer. If you >>>>> accept that a type should support iteration with a `for...in` loop, then >>>>> what is your basis for claiming that these extension methods are >>>>> "separate functionalities”? >>>> >>>> Just because you *can* express something in code doesn’t mean you should, >>>> or that it’s correct. It is objectively false to say a Set has a first or >>>> last object, because the objects therein have no order. You can take a >>>> random object from the set and call it “first”, but that doesn’t make that >>>> a correct definition of Set.first. A Set has no order, a specific >>>> iteration has an “order” only in the sense that all and only the objects >>>> in the set have to come out one at a time, but that doesn’t mean the Set >>>> itself has an order, specifically a first or last object. >>> >>> Since Set conforms to Collection, it is guaranteed that if one element of >>> an instance of Set comes out first one time, it'll come out first every >>> time from that instance. If it helps, think of Swift's Set as modeling >>> (imperfectly, as all models must) both a mathematical set and a multi-pass >>> sequence, just as Swift's Int models both an integer and a sequence of bits. >>> >>>> You’re a fan of the principal of least surprise. Tell me, which would be >>>> less surprising: Set.dropFirst() actually drops a random element, or Set >>>> doesn’t have a dropFirst()? And if you think dropFirst() removing an >>>> element at random is not surprising, please explain why. >>> >>> I think Set.dropFirst removing the first element that I observe on >>> iteration is the least surprising answer, because Swift tells me that the >>> stdlib Set models a set but that it is also a sequence. >> >> The latter is exactly the problem Kevin did point out. A Set is an Iterable >> (in the sense that I can iterate over its elements with the order being a >> meaningless random side effect) but it is *not* a Sequence (in the sense >> that the order conveys any meaning). > > Swift's Sequence protocol does not require the order of iteration to "convey > any meaning"; it doesn't even require it to be deterministic.
Exactly. This is what makes methods like `first(where:)` meaningless which is why separating Sequence into Iterable and Sequence makes sense. -Thorsten > >> >> -Thorsten >> >>> >>>>>>>>> […] >>>>>>>> >>>>>>>>> * If a type `T` conforms to `ForLoopable` and an instance `t` of that >>>>>>>>> type has at least one element, then *something* has to be the first >>>>>>>>> element in a `for element in t { ... }` loop. Put another way, every >>>>>>>>> instance of a type that conforms to `ForLoopable` must have at least >>>>>>>>> one publicly observable order (although, intriguingly, I'm not sure >>>>>>>>> it has to be a repeatable one). It is possible, therefore, to have a >>>>>>>>> semantic answer to the question of which element is `first` or (if >>>>>>>>> finite) `last`; one can also `drop(while:)`, etc., and perform >>>>>>>>> lexicographical comparisons. >>>>>>>> >>>>>>>> As a side effect of Swift being a procedural language each iteration >>>>>>>> happens to occur in some order, yes, but that order is meaningless and >>>>>>>> reflects nothing about the Set itself. In fact, I’d say that `first`, >>>>>>>> `last`, etc. are not even defined on the original Set per se, only on >>>>>>>> the specific order that a particular iteration resulted in. And that >>>>>>>> order is not necessarily predictable, nor necessarily stable, as you >>>>>>>> yourself said. >>>>>>>> >>>>>>>> Consider an Iterable that gives a different order every time it’s >>>>>>>> iterated. >>>>>>>> Should calling `.first` or `last` give a different object every time? >>>>>>>> That’s absurd. >>>>>>>> Should an object lexicographically compare not equal to itself? Even >>>>>>>> more absurd. >>>>>>> >>>>>>> What's your basis for saying that such behavior is absurd? It is >>>>>>> explicitly permitted for instances of types conforming to `SpongeBob` >>>>>>> to be single-pass and/or infinite. For a single-pass `SpongeBob`, >>>>>>> `first` will certainly return a different value every time it is >>>>>>> invoked. >>>>>> >>>>>> Is `first` mutating? No. Should it be? No! `first` and `last` are a peek >>>>>> at the state of the object. >>>>> >>>>> You're right, `first` should not be mutating; that's actually an >>>>> important design consideration, as Ole pointed out, and it's not actually >>>>> available on `Sequence` for that reason. However, `first { _ in true }` >>>>> is available and is potentially mutating, as are all methods on Sequence >>>>> by design. >>>>> >>>>>> Is `elementsEqual` (or *shudder* lexicographicallyEqual) reflexive? IMO >>>>>> it clearly should be. Especially with the “lexicographically” part—from >>>>>> everything I can find, a lexicographical ordering is by definition >>>>>> reflexive. Do you have a citation for the idea that lexicographical >>>>>> equality can legitimately be non-reflexive? >>>>> >>>>> Clearly (tautologically?), such a function should be reflexive for any >>>>> argument ordered with respect to itself. However, if there is no >>>>> lexicographical comparison possible, then a thing cannot compare >>>>> lexicographically equal to anything, even itself. >>>> >>>> And that’s PRECISELY why lexicographicallyEqual does not make sense to >>>> apply to unordered sets. There is no lexicographical comparison possible, >>>> so why do you keep insisting they should have a method that falsely claims >>>> to lexicographically compare them? >>> >>> I agree! It doesn't make sense if no comparison is possible! But Swift >>> tells me that a `Set` is a `Sequence`! >>>>> >>>>>> A random number generator fulfills all the semantic requirements of >>>>>> conforming to `SpongeBob`, and in fact I do just that in NumericAnnex. >>>>>> `first` gives a different value every time, and a randomly generated >>>>>> `SpongeBob` would unsurprisingly compare lexicographically not equal to >>>>>> itself. >>>>> >>>>> > IMO that’s a bug in the implementation; lexicographical equality is >>>>> > reflexive, period. >>>>> >>>>> > Presumably the `elementsEqual` method contains something along these >>>>> > lines (take from SequenceAlgorithms.swift.gyb): >>>>> >>>>> var iter1 = self.makeIterator() >>>>> var iter2 = other.makeIterator() >>>>> >>>>> > By creating two iterators, you’re mutating while iterating. Turns out >>>>> > there’s even a warning against this in Sequence.swift: >>>>> >>>>> /// Using Multiple Iterators >>>>> /// ======================== >>>>> /// >>>>> /// Whenever you use multiple iterators (or `for`-`in` loops) over a >>>>> single >>>>> /// sequence, be sure you know that the specific sequence supports >>>>> repeated >>>>> /// iteration, either because you know its concrete type or because the >>>>> /// sequence is also constrained to the `Collection` protocol. >>>>> /// >>>>> /// Obtain each separate iterator from separate calls to the sequence's >>>>> /// `makeIterator()` method rather than by copying. Copying an iterator is >>>>> /// safe, but advancing one copy of an iterator by calling its `next()` >>>>> method >>>>> /// may invalidate other copies of that iterator. `for`-`in` loops are >>>>> safe in >>>>> /// this regard. >>>>> >>>>> > The default implementation of elementsEqual is therefore unsafe because >>>>> > it has the potential for using an invalidated iterator. >>>>> >>>>> You are misunderstanding the warning in the second paragraph here. The >>>>> implementation (not a default implementation, unless I'm mistaken, as it >>>>> cannot be overridden) >>>> >>>>> makes each iterator using separate calls to `makeIterator()`, just as the >>>>> documentation tells you to do. Calling next() on one iterator does not >>>>> invalidate the other iterator, because the second is not a copy of the >>>>> first. >>>> >>>> Indeed, I misread that comment. >>>> That said, is there a well-defined behavior when iterating a one-shot >>>> sequence with two iterators? >>>> (It *is* a default implementation, btw) >>> >>> Not sure about that; I don't see a protocol requirement, in which case it >>> can only be shadowed in a concrete type but it can't be overridden. How to >>> accommodate single-pass sequences is an interesting question. Off the top >>> of my head, an iterator would have to be or wrap a reference type. >>>>> >>>>> You are, however, right that calling `rng.elementsEqual(rng)` is not >>>>> advised. It isn't unsafe; it's just not useful. That said, calling >>>>> `array.elementsEqual(array)` is equally safe and equally useless, and the >>>>> uselessness of such a reflexive comparison is neither here nor there. >>>> >>>> Funny how you complain about my code being useless and yet you insist >>>> below, "If it's not providing you with utility, then don't use it.” >>>> Regardless, you’re wrong to dismiss this case. `foo.elementsEqual(foo)` on >>>> its own makes little sense, sure, but you could easily find yourself in a >>>> method comparing two iterators you obtained from elsewhere, and >>>> occasionally they happen to be the identical object. Allowing an iterator >>>> to return `false` for .elementsEqual on itself is unexpected and dangerous. >>> >>> You will always have to account for this possibility, because Swift's >>> `Equatable` explicitly allows "special values" to be not equal to >>> themselves. This is, at least in part, in order to accommodate the IEEE >>> decree that NaN != NaN: >>> >>> ``` >>> let x = [Double.nan] >>> x.elementsEqual(x) // false >>> ``` >>> >>> Changing this behavior is way beyond the scope of this thread (and has been >>> the topic of hours (actually, weeks and weeks) of fun on this list >>> previously). >>> >>>>>>> On the other hand, if I have a collection of objects that I want >>>>>>> iterated in a particular order, I can use a container that iterates in >>>>>>> a specific, known, well-defined way, and use that to construct the >>>>>>> sequence of objects. That’s clearly an Iterable collection, but the >>>>>>> guarantee is stronger than that. Since it iterates objects in a >>>>>>> specific sequence, the logical way to express that would be `Sequence: >>>>>>> Iterable`. Again, we’ve seen that before. >>>>>>> >>>>>>> Now, since a Sequence is guaranteed to iterate the same every time, >>>>>>> suddenly our `first`, `last`, `drop*`, etc. methods have a meaning >>>>>>> inherent to the collection itself, rather than a specific iteration. >>>>>> >>>>>> What you call a "Sequence" here would have to be multi-pass, finite, and >>>>>> ordered. >>>>> >>>>> > Ordered, yes, but it’s only admittedly poor wording that suggests >>>>> > multi-pass, and I don’t think anything there suggests finite. >>>>> >>>>> If a Sequence is "guaranteed to iterate the same every time," then surely >>>>> it must be multi-pass; what's the alternative? >>>> >>>> Not sure if you just missed the very next sentence or are actively >>>> ignoring it just to be argumentative. I already acknowledged that that >>>> phrase didn’t convey the meaning I intended, and a Sequence is not and >>>> should not be required to be multi-pass. >>> >>> I entirely misunderstood your next sentence as asserting that being >>> multi-pass makes the iteration order well-defined. >>>>> >>>>>> It would be better to say that the iteration order is well-defined. That >>>>>> will almost always mean documented, and usually predictable though >>>>>> obviously e.g. RNGs and iterating in random order will not be >>>>>> predictable by design. >>> Wouldn't it then suffice to document, say, that a set's iteration order is >>> the insertion order? >>>>>> >>>>>>> That's actually more semantically constrained than what Swift calls a >>>>>>> `Collection` (which requires conforming types to be multi-pass and(?) >>>>>>> finite). By contrast, Swift's `SpongeBob` protocol explicitly permits >>>>>>> conforming single-pass, infinite, and/or unordered types. >>>>>> >>>>>> I think you’re talking about Sequence here, I’ve lost track of your >>>>>> nonsense by now. Yes, the current Swift protocol named Sequence allows >>>>>> unordered types. You seem to keep asserting that but not actually >>>>>> addressing my argument, which is that allowing Sequences to be unordered >>>>>> with the current API is undesired and actively harmful, and should >>>>>> therefore be changed. >>>>> >>>>> What is harmful about it? >>>> >>>> Well, for one, the issue you raised this thread about—two sets that are >>>> `==` could return either true or false for `elementsEqual`, depending on >>>> how they arrived at their current state. That’s not acceptable, and the >>>> problem isn’t with the name of the method. >>> >>> Apple documentation calls this one of the "order-dependent" methods. It is >>> surely acceptable for a type that conforms to an order-dependent protocol >>> to have methods that are order-dependent; they do, however, have to be >>> clearly order-dependent to avoid confusion on unordered types. >>> >>>> Then there are all the methods that imply a specific order of iteration. >>>> If the “sequence” is unordered, who knows what you’ll get? It is >>>> incredibly easy for an engineer to write a method that implicitly relies >>>> on a passed sequence being intrinsically ordered and another engineer to >>>> pass it an unordered “sequence.” The first engineer could neglect to >>>> document the dependency, or even not notice it; or the second engineer >>>> could just fail to read the documentation thoroughly enough. There is >>>> currently no way for the compiler to enforce passing only an object that >>>> is (or at least claims to be) intrinsically ordered. >>> >>> It is also incredibly easy for such an engineer to use `for...in` instead >>> to accomplish the same task, generic over ordered and unordered sequences >>> whatever you name such distinguished protocols. I think your beef really >>> still boils down to Set being compatible with `for...in` at all, as Jon >>> acknowledges. >>>>> >>>>>> >>>>>>> As long as it is possible to iterate over a `SpongeBob`, it is >>>>>>> meaningful to ask what element is first obtained upon iteration or to >>>>>>> drop the first element obtained upon iteration. >>>>>>> And as long as iteration is not required to be repeatable (and it >>>>>>> isn't), it is perfectly acceptable for these algorithms to return a >>>>>>> different result every time. >>>>>> >>>>>> It is “meaningful” in the sense that it can technically be programmed. >>>>>> The actual results are meaningless beyond returning or dropping a >>>>>> random* element. >>>>>> >>>>>> *: Don’t nitpick the word “random”, you know exactly what I mean. It’s >>>>>> just shorter and no less clear than “technically more-or-less >>>>>> deterministic but not documented, not generally predictable, and >>>>>> probably but not necessarily consistent from one call to the next." >>>>> >>>>> I fail to see the issue here. If it's not providing you with utility, >>>>> then don't use it. >>>> >>>> I have no problem with functions I don’t use provided they are >>>> well-defined and reasonably accurately named. Functions requiring an order >>>> on unordered collections don’t pass that bar. >>> >>> As I said, you're welcome to tackle the protocol hierarchy, but I really >>> doubt it's within the realm of realistic endpoints for Swift 5. I'm just >>> trying to propose a narrowly targeted pragmatic solution to one specific >>> limited harm that might be deliverable by the next point release. As a >>> great man once said, Swift is a pragmatic language. >>>>> Since Collections do guarantee multi-pass iteration, Brent's example of >>>>> `set.dropFirst().reduce(set.first!, ...)` provides just one instance >>>>> where an unordered Collection can profitably make use of `first`. >>>>> Permitting generic algorithms that can operate on either arrays or sets, >>>>> for example, is the desired effect of having such a protocol; a generic >>>>> algorithm that takes a Collection can ask for the first element, and in >>>>> the case of an unordered Collection, an arbitrary element will do just >>>>> fine. >>>> >>>> The generic algorithms should be on a protocol that specifies everything >>>> they require. If one can work on anything you can iterate over, put it on >>>> Iterable. If another requires the objects to be ordered, put it on >>>> Sequence. Need to express that an algorithm requires a multi-pass >>>> sequence? Make a MultiPassSequence protocol and put the algorithm on an >>>> extension containing that requirement. Use protocols to express >>>> requirements, as they were designed for. Don’t just tack a bunch of >>>> methods onto a protocol that isn’t sufficient to describe their >>>> requirements and say, “oh, by the way, only use this method if your >>>> implementation meets these conditions…" >>> >>> The benefits are likely outweighed by the costs of such an approach taken >>> to completion, because there are many axes to differentiate. The protocol >>> hierarchy for collections is already daunting, leading to monstrosities >>> such as `MutableRangeReplaceableRandomAccessSlice`. It stretches the bounds >>> of sensibility to have a >>> `LazyUnorderedInfiniteMultiPassMutableRangeReplaceableRandomAccessSlice`. >>> >>> The Swift stdlib deliberately eschews modeling everything in protocol >>> hierarchies with the highest level of granularity. There's some fudging, >>> deliberately, to find a happy medium between obtuse and approachable, >>> between too many/too specialized and not enough. For example, I pushed for >>> protocols such as `Field` and `Ring` at the top of the numeric hierarchy, >>> which might allow complex number types to slot into the hierarchy more >>> sensibly, for example. But we have a compromise protocol `Numeric` which >>> doesn't quite have the same guarantees but is much more approachable. >>> Notice that we also don't break down numeric protocols into `Addable`, >>> `Subtractable`, etc.; we also have that fudge factor built into >>> `Equatable`, as I mentioned. >>>>>>> >>>>>>>> `first` is the first object in the Sequence. It doesn’t matter how the >>>>>>>> sequence came to be in that order; it doesn’t matter whether or not >>>>>>>> the sequence has already been iterated or how many times. `first` is >>>>>>>> the first object that is, was, and always will be presented by the >>>>>>>> Sequence’s Iterator. (Until the collection is mutated, obviously). >>>>>>>> >>>>>>>> To summarize, >>>>>>>> A Set has no intrinsic order. You can iterate over it, and a specific >>>>>>>> iteration of a set has an order, but that order is not tied to the Set >>>>>>>> itself beyond including all and only the items therein. Therefore, the >>>>>>>> Set itself has no intrinsic `first`, `last`, lexicographical >>>>>>>> comparison, etc.; only its iterations do, and they are not themselves >>>>>>>> Sets. >>>>>>>> A Sequence does have an intrinsic order. The order of iteration >>>>>>>> reflects the order inherent to the Sequence. Therefore, a Sequence has >>>>>>>> a `first`, `last`, lexicographical comparison, etc. >>>>>>>> >>>>>>>> Just in case it’s not obvious, `Set` here is pretty much >>>>>>>> interchangeable with any other unordered iterable. >>>>>>> >>>>>>> What you want to call a "Sequence" is what Swift calls a `Collection`, >>>>>>> with additional restrictions. What you want to be called "Iterable" is >>>>>>> what Swift calls `Sequence` (or now, `SpongeBob`). Clearly, shuffling >>>>>>> names will not make these protocols support any more functionality, so >>>>>>> that can be put aside. >>>>>> >>>>>> No, no, no! What I want to call “Iterable” is specified below. It is >>>>>> about HALF of what’s currently in Sequence—the half that has to do with >>>>>> iterating, whence the name. >>>>>> What I want to call Sequence is precisely what Swift now calls >>>>>> Sequence—the methods that are in Iterable by virtue of adopting >>>>>> Iterable, PLUS some methods that only make sense on iterable groups of >>>>>> objects where the iteration order is well-defined. >>>>>> >>>>>>> >>>>>>> Now, with that out of the way, why do you think that only `Collection` >>>>>>> types should have `first` and `last`? These helper properties and >>>>>>> methods are simply convenient ways to spell things that can be done >>>>>>> with `for...in`--the whole point of supplying them is to allow people >>>>>>> to work with these types in a more functional style. >>>>>> >>>>>> Apparently “collection" was a bad choice of word. What I clearly meant >>>>>> was not the current Swift Collection protocol, but rather an unordered >>>>>> assemblage of objects. UnorderedCollection, perhaps, or if that’s still >>>>>> going to cause issues, try UnorderedAssemblage. What `first` and `last` >>>>>> really mean in an UnorderedAssemblage is give me some object from the >>>>>> assembled objects, I don’t care which one. For which it’s much more >>>>>> clear to have an `anyObject()` as on NSSet; as another user has pointed >>>>>> out, `assemblage.makeIterator().next()` works just as well. (I just >>>>>> checked, and that’s actually how `first` is implemented. But it’s on >>>>>> Collection, which is guaranteed to be multipass,) >>>>> >>>>> Again, the point of having a protocol-based design is to allow useful >>>>> _generic_ algorithms to be written; that `first` and `last` would be >>>>> equivalent to an arbitrary element in the case that a collection is >>>>> unordered is not at all an argument against these types conforming to >>>>> `Collection`; if anything, it's an argument for it. >>>> >>>> If a protocol demands the first object, you should give it the first >>>> object. If you don’t have a first object, maybe you shouldn’t conform to >>>> the protocol. If the protocol really just needs any old object, call it >>>> `anyObject`. >>> >>> Sure, but we *do* have a first element; it just happens to be the first >>> that is obtainable on iteration. That you could make a good case for any >>> other element to be first doesn't mean that this one isn't a perfectly >>> cromulent first. >>> >>>> >>>>> Just as `Sequence.underestimatedCount` is equivalent to >>>>> `Collection.count` for types that conform to `Collection`, or the >>>>> instance `BinaryInteger.bitWidth` is equivalent to a static `bitWidth` >>>>> for types that conform to `FixedWidthInteger`. >>>> >>>> I don’t see how those are relevant, they all mean what they claim to, >>>> unlike Set.first/dropFirst/etc. >>>> >>>>>>>>>>>>> public protocol Iterable { >>>>>>>>>>>>> associatedtype Iterator: IteratorProtocol >>>>>>>>>>>>> func map<T>(...) -> [T] // Iterable where .Iterator.Element == T >>>>>>>>>>>>> func filter(...) -> [Iterator.Element] // Iterable where >>>>>>>>>>>>> .Iterator.Element == Self.Iterator.Element >>>>>>>>>>>>> func forEach(...) >>>>>>>>>>>>> func makeIterator() -> Iterator >>>>>>>>>>>>> var underestimatedCount: Int { get } >>>>>>>>>>>>> } >>>>>>>>>>>>> >>>>>>>>>>>>> public protocol Sequence: Iterable { // Maybe OrderedSequence >>>>>>>>>>>>> just to make the well-defined-order requirement explicit >>>>>>>>>>>>> associatedtype SubSequence >>>>>>>>>>>>> func dropFirst(...) -> SubSequence // Sequence where >>>>>>>>>>>>> .Iterator.Element == Self.Iterator.Element >>>>>>>>>>>>> func dropLast(...) -> SubSequence // " " >>>>>>>>>>>>> func drop(while...) -> SubSequence // " " >>>>>>>>>>>>> func prefix(...) -> SubSequence // " " >>>>>>>>>>>>> func prefix(while...) -> SubSequence // " " >>>>>>>>>>>>> func suffix(...) -> SubSequence // " " >>>>>>>>>>>>> func split(...where...) -> [SubSequence] // Iterable where >>>>>>>>>>>>> .Iterator.Element == (Sequence where .Iterator.Element == >>>>>>>>>>>>> Self.Iterator.Element) >>>>>>>>>>>>> } >>>>>>>> >>>>>>>> >>>>>>>> And just to be explicit, >>>>>>>> struct Set: Iterable {…} >>>>>>>> struct Dictionary: Iterable {…} >>>>>>>> struct Array: Sequence {…} >>>>>>>> etc. >>>>>>>> >>>>>>>> Hopefully at some point: >>>>>>>> struct OrderedSet: Sequence {…} >>> >> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org >>> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution