> Am 18.10.2017 um 22:36 schrieb Michael Ilseman <milse...@apple.com>: > > > >> On Oct 18, 2017, at 12:24 PM, Thorsten Seitz <tseit...@icloud.com >> <mailto:tseit...@icloud.com>> wrote: >> >>> >>> Am 17.10.2017 um 20:47 schrieb Michael Ilseman via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>: >>> >>> >>> >>>> On Oct 17, 2017, at 10:15 AM, Kevin Nattinger via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>> >>>>> Because, in my analysis, the problem is that the method is incorrectly >>>>> named. The problem affects all types that conform to Sequence and not >>>>> just Set and Dictionary; elementsEqual is a distinct function from ==, >>>>> and it must either continue to be distinct or cease to exist, but its >>>>> name does nothing to clarify any distinction. >>>> >>>> In my analysis, the problem is the method's implementation. As I see it, >>>> the only use for `elementsEqual` is as a replacement for `==` when two >>>> objects are different types (or not known to be the same)—equal elements, >>>> and IF the sequences have an order, in the same order. Could you provide >>>> an example where `elementsEqual` randomly returning either true or false >>>> depending on internal state alone is a legitimate and desirable result? >>>> >>> >>> It doesn’t randomly return true or false, it consistently returns true or >>> false for the *same* pair of Sequences. What *same* means, of course, is >>> complicated and exists at two levels (as we have two ways of talking about >>> *same*). >> >> >> It is random (for unordered collections) from the standpoint of business >> logic. > > Could you define what you mean by “business logic”? Is this is a subset of > programming in Swift, and if so what is in it? Can users define their own > types in this subset? Also, why would arguments made in that subset also > apply to all of Swift?
>From Wikipedia: "In computer software ><https://en.wikipedia.org/wiki/Software>, business logic or domain logic is >the part of the program that encodes the real-world business rules ><https://en.wikipedia.org/wiki/Business_rule> that determine how data can be >created, stored, and changed ><https://en.wikipedia.org/wiki/Create,_read,_update_and_delete>. It is >contrasted with the remainder of the software that might be concerned with >lower-level details of managing a database ><https://en.wikipedia.org/wiki/Database> or displaying the user interface ><https://en.wikipedia.org/wiki/User_interface>, system infrastructure, or >generally connecting various parts of the program.“ (https://en.wikipedia.org/wiki/Business_logic) I explained why there is no possibility to use `elementsEqual` with unordered collections like Set except for the single use case of comparing the elements of a set with themselves, i.e. `set.elementsEqual(set)`. > >> The order of the elements of a Set, while publicly observable, cannot be >> influenced by business logic because it is an implementation detail. > > Yes, this is what Set means when it says: “You use a set instead of an array > when you need to test efficiently for membership and you aren’t concerned > with the order of the elements in the collection, or when you need to ensure > that each element appears only once in a collection.” (emphasis mine) Exactly. I am well aware that Sets are unordered. This whole discussion revolves around `elementsEqual` being not appropriate for unordered collections like Set. -Thorsten >> Therefore it is not possible to write business logic that exploits this >> order, i.e. it is not possible to write business logic using `elementsEqual` >> on a Set. >> The only exception is using the receiver as argument, i.e. >> `set.elementsEqual(set)` because in this case, and in this case alone, the >> result is independent of the effectively random order. >> Therefore the single use case for `elementsEqual` for unordered collections >> is calling `set.elementsEqual(set)` to determine whether a Set of Floats >> contains NaN values. I claim that this is better written as `set.contains { >> $0.isNaN }` which works nicely for a Set<Float> and is intention revealing >> as opposed to using `elementsEqual`. >> >> As I have shown this really is the *single* use case for `elementsEqual` for >> unordered collections. There can be no other use case. >> All other uses of `elementsEqual` involving two different collections where >> one is an unordered collection have random results that have absolutely no >> business meaning and therefore are bugs. >> >> Therefore having `elementsEqual` as API for unordered collections is a >> source of bugs except for a single use case which has a better solution >> using `contains`. That is why I would like to split the API. >> >> Adam expressed the concern that this required `map` to implemented >> separately for the split APIs: `Iterable.map` would have to return an >> `Iterable` whereas `Sequence.map` would have to return a `Sequence`. >> This is an independent issue IMO, because currently we have a similar >> situation: `Collection.map` does not return a `Collection` either. It >> returns an Array. This is a compromise partly due to missing language >> features which can simply remain when `Sequence` is split. >> >> Actually the question for the correct return type for `map` is not a simple >> one. For a `Dictionary` we would probably want to get a `Dicitonary` where >> the values have been replaced by the mapped ones (this is how Smalltalk does >> it). But for `Set` we typically do *not* want a `Set` because in general we >> will be interested in duplicate mapped values. There are times where a `Set` >> would be the correct return type but this applies to ordered collections or >> dictionaries as well, so there should be a variant (or an argument with a >> default) allowing to provide the desired result type or target collection. >> But this is a completely separate issue which can be easily deferred until >> the planned language features have arrived which might help finding a good >> solution for this question. Until then we will just use the current >> implementation which returns an array. >> >> To get back to the topic at hand: I propose to differentiate between >> unordered and ordered collections because I think that this is an important >> distinction with tractable impact on algorithms (as shown above). The method >> `elementsEqual` would be part of the ordered sequence protocol and I would >> suggest the name `elementsPairwiseEqual`. >> > > You are free to propose that and justify its cost. You'll probably want to > plan on how you’ll present the cost/benefit analysis for the feedback of “why > not just slap a warning on Set/Dictionary?” > > >> -Thorsten >> >> >> >>> >>> I apologize for not reading every email in depth in this thread (they are >>> coming in faster than I can parse them), but let me try to present >>> motivation for this and hopefully provide more shared understanding. >>> >>> We have two forms of equality we’re talking about: equality of Sequence and >>> equality of the elements of Sequences in their respective ordering. `==` >>> covers the former, and I’ll use the existing (harmful) name of >>> `elementsEqual` for the latter. >>> >>> `==` conveys substitutability of the two Sequences. This does not >>> necessarily entail anything about their elements, how those elements are >>> ordered, etc., it just means two Sequences are substitutable. >>> `elementsEqual` means that the two Sequences produce substitutable >>> elements. These are different concepts and both are independently useful. >>> >>> Cases: >>> >>> 1. Two Sequences are substitutable and produce substitutable elements when >>> iterated. `==` and `elementsEqual` both return true. >>> >>> Example: Two arrays with the same elements in the same order. >>> >>> >>> 2. Two Sequences are substitutable, but do not produce substitutable >>> elements when iterated. `==` returns true, while `elementsEqual` returns >>> false. >>> >>> Example: Two Sets that contain the same elements but in a different order. >>> >>> Contrived Example: Two Lorem Ipsum generators are the same generator >>> (referentially equal, substitutable for the purposes of my library), but >>> they sample the user’s current battery level (global state) each time they >>> produce text to decide how fancy to make the faux Latin. They’re >>> substitutable, but don’t generate the same sequence. >>> >>> >>> 3. Two Sequences are not substitutable, but produce substitutable elements >>> when iterated. `==` returns false, while `elementsEqual` returns true. >>> >>> Example: Consider two sequences that have differing identity. `==` operates >>> on an identity level, `elementsEqual` operates at an element level. >>> >>> Contrived Example: InfiniteMonkeys and Shakespeare both produce the same >>> sonnet, but they’re not substitutable for my library’s purposes. >>> >>> >>> 4. Two Sequences are not substitutable and don’t produce substitutable >>> elements when iterated. `==` and `elementsEqual` both return false. >>> >>> Example: `[1,2,3]` compared to `[4,5,6]` >>> >>> >>> It is true that situations #2 and #3 are a little harder to grok, but they >>> are what illustrate the subtle difference at hand. I think situation #2 is >>> the most confusing, and has been the primary focus of this thread as Set >>> exists and exhibits it. >>> >>> >>> Now, onto naming. `elementsEqual` is a very poor choice of name for the >>> concept of equality of elements in their respective orderings, as it >>> doesn’t highlight the “in their respective orderings” part. >>> `lexicographicallyEqual` highlights the ordering much better, as “abc” is >>> not lexicographically equal to “cba” despite having equal elements. I think >>> it is clearly an improvement over the status quo. I like something a little >>> more explicit (e.g. `elementsOrderedEqual`), personally, but I don’t care >>> that strongly. I’m just glad to see `elementsEqual` getting some >>> clarification. >>> >>> >>> >>> >>>>> >>>>> Thanks, >>>>> Jon >>>>> _______________________________________________ >>>>> swift-evolution mailing list >>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution