Regards (From mobile)
> On May 16, 2016, at 8:16 PM, Thorsten Seitz via swift-evolution > <[email protected]> wrote: > > >>> Am 16.05.2016 um 17:04 schrieb Karl via swift-evolution >>> <[email protected]>: >>> >>> internal func _arrayOutOfPlaceReplace >>> <B: _ArrayBufferProtocol, C: Collection> >>> (_ source: inout B, _ bounds: Range<Int>, _ newValues: C, _ insertCount: >>> Int) >>> where >>> C.Iterator.Element == B.Element, >>> B.Index == Int >>> { >>> >>> Now only the relatively unimportant details—that the buffer and collection >>> must have elements of the same type, and that the buffer must have integer >>> indices—are at the end, whereas the basic conformances required to make any >>> sense at all of the declaration are still inline. >> >> You see, I’m of the complete opposite opinion - I don’t think those details >> are “relatively unimportant”; I think they’re absolutely critical. >> >> If you try and call it when your C.Iterator.Element is not equal to >> B.Element, the function does not exist. You’re talking about some other >> function in that case, not this one. >> >> Same goes if B.Index is not an Int. If that was an unimportant detail, they >> would have given ‘bounds’ the type Range<B.Index> and not specified any >> constraints at all. The function requires the index be an Int - maybe it’s >> doing some mathematical operations which wouldn’t make sense for a more >> complex index type, such as DictionaryIndex. >> >> Basically that is it - the ‘where’ clause is a vital part of the function >> declaration; it defines the specification under which the function exists at >> all (along with the function name, arguments and return type). If you don’t >> match every single part of that specification, the type checker won’t match >> your call to this function - if you don’t meet the constraints, you’re not >> talking about this function; imagine you have several overloaded function >> declarations which differ only by ‘where’ condition: >> >> func insert<T>(contentsOf:T) where T:RandomAccessCollection, T.Element == >> Element >> func insert<T>(contentsOf:T) where T:Collection, T.Element == Element >> func insert<T>(contentsOf:T) where T:Sequence, T.Element == Element >> … etc >> >> the ‘where’ clause isn’t incidental here - it’s the only disambiguating >> feature between these declarations. I think it’s critical information and >> shouldn’t be stuffed at the end because you think it’s not important; it is >> important. If it hinders initial readability of the declaration so much, you >> can wrap it behind a typealias: >> >> func insert<T: RandomAccessCollectionOf<Element>>(contentsOf: T) >> func insert<T: CollectionOf<Element>>(contentsOf: T) >> func insert<T: SequenceOf<Element>>(contentsOf: T) >> … etc > > Either you have the constraints first and the parameter list last or the > other way around. Fact is that *both* decide whether it is the function you > need. > So just their order cannot help with that. > I would still argue that the proposed version is more readable: just look at > your example above where the first part up to the where is identical at one > glance, so that the disambiguating part stands out whereas your other example > looks much more unstructured because of the different lengths of the generic > type list which makes the congruence of the parameter lists difficult to see > because they do not align anymore. > >> >> I think that’s much easier to follow, and attempts to reduces the length and >> verbosity of the where clauses (i.e. like the fact that Collection’s >> associated type referring to its element is called ‘Element’; ‘CollectionOf’ >> encodes an equivalent constraint in less characters). This proposal just >> feels kind of lazy - we’ll just tack them on the end so we can ignore them a >> bit more easily, even though they’re still going to be monstrously long and >> difficult-to-read. > > The typealias idea can be combined with the where clause at the end: > > func insert<T>(contentsOf:T) where T:RandomAccessCollectionOf<Element> > func insert<T>(contentsOf:T) where T:CollectionOf<Element> > func insert<T>(contentsOf:T) where T:SequenceOf<Element> > > Much easier to discern (at least IMO) because everything is aligned. > >> >> Are there any other languages that do this? Or anything even similar? It >> seems to me that the context-switching is something that human beings in >> general are not going to find very legible; like if you insert too many >> commas in a sentence. > > Yes, Ceylon places all constraints (it only knows inheritance constraints) at > the end: > > shared Value sum<Value>({Value+} values) > given Value satisfies Summable<Value> { ... } > shared <Key->Item>[] zip<Key,Item>({Key*} keys, {Item*} items) > given Key satisfies Object > given Item satisfies Object { ... } > > It does the same for type definitions: > shared class Singleton<out Element>(Element element) > extends Object() > satisfies [Element+] > given Element satisfies Object { ... } > This confirms my impression that WHERE does not fit as well at the end as if the information was inlined. WITH is my preferred replacement, which IMO has a similar connotation as ceylon's GIVEN. > >> >>>> On 15 May 2016, at 16:05, Brent Royal-Gordon via swift-evolution >>>> <[email protected]> wrote: >>>> >>>> There we are. I read the declaration of the function from beginning to end >>>> and gradually formed a rough understanding of it without needing to change >>>> my expectations halfway through. I still have doubts about 'insertCount', >>>> but I was at least able to formulate an hypothesis about its use. >>>> >>>> YMMV, but as far as I'm concerned, the original declaration was much easier >>>> to understand. >>> >>> I actually agree with you for this case, but not *all* type information >>> *has* to be moved to the end. Try this on for size, which is actually still >>> the most natural way to write this declaration in SE-0081: >>> >>> >>> This proposal *permits* you to hollow out the generic parameter list to the >>> point of vacuousness, but that doesn't mean it's the right thing to do. It >>> might make sense to ban a direct `X: Foo` requirement unless there was >>> already an `X: Bar` in the generic parameter list. Or we might simply need >>> to paraphrase the Perl manual page: "There are several ways to write a >>> generic requirement, so consider picking the most readable one." >>> >>> -- >>> Brent Royal-Gordon >>> Architechies >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] >> https://lists.swift.org/mailman/listinfo/swift-evolution > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
