> On 5 Oct 2017, at 20:23, Ben Cohen via swift-evolution > <swift-evolution@swift.org> wrote: > > >> On Oct 5, 2017, at 10:58, Nate Cook via swift-evolution >> <swift-evolution@swift.org> wrote: >> >> The edge case is really the same (empty ranges), it’s about what we do with >> the edge case. If we include the methods on integer types, usage will look >> like this: >> >> let x = Int.random(in: 0..<5) // 3 >> let y = Int.random(in: 0..<0) // runtime error >> > > These examples are a bit misleading, because they use literals. Sometimes > they will, sure, but in practice, many use cases would define Int.random(in: > 0..<array.count) or similar, which has just the same pitfalls as > array.random(). > > p.s. ideally Int.random(in: 0..<0) would be a compile time error... > >> If we only have the collection methods, usage will look like this: >> >> let x = (0..<5).random()! // 3 >> let y = (0..<0).random()! // runtime error >> > > I don’t know if it’s a given that we must make randomElement optional. I’m on > the fence as to whether it should be optional vs trap on empty.
I vote for making them optional because doing otherwise would be inconsistent with first and last, no? > Another option is to shadow randomElement on closed range to be non-optional. > >> But my suspicion is that lots of people will write things like this: >> >> guard let x = (0..<5).random() >> else { fatalError("not gonna happen") } >> >> I’d rather have the numeric methods trap than add the optional unwrapping >> step to every one of these calls. For me, getting a random number and >> picking a random element of a collection are two different operations—where >> it’s common to work with empty collections, especially in generic code, >> trying to get a random value from an empty range is really a programming >> error. I think it’s okay for them to have slightly different semantics. >> >> Nate >> >> >>> On Oct 5, 2017, at 12:27 PM, Alejandro Alonso <aalonso...@outlook.com> >>> wrote: >>> >>> Rather 0 ..< 0 my bad. I think if we include closedcountable, then there >>> needs to be support for countable, but there are edge cases where users can >>> input invalid ranges for countable. >>> >>> Enviado desde mi iPhone >>> >>> El oct. 5, 2017, a la(s) 12:22, Alejandro Alonso via swift-evolution >>> <swift-evolution@swift.org> escribió: >>> >>>> I agree with Ben here because users can still enter an invalid range with >>>> the static function. I.E. Int.random(in: 0 ... 0). >>>> I would really prefer excluding these static functions from numeric types. >>>> >>>> - Alejandro >>>> >>>> El oct. 5, 2017, a la(s) 12:03, Nate Cook via swift-evolution >>>> <swift-evolution@swift.org> escribió: >>>> >>>>>> On Oct 5, 2017, at 11:30 AM, Ben Cohen via swift-evolution >>>>>> <swift-evolution@swift.org> wrote: >>>>>> >>>>>>> On Oct 4, 2017, at 9:12 PM, Chris Lattner via swift-evolution >>>>>>> <swift-evolution@swift.org> wrote: >>>>>>> >>>>>>>> ``` >>>>>>>> extension Int { >>>>>>>> static func random(in range: Countable{Closed}Range<Int>) -> Int >>>>>>>> } >>>>>>> >>>>>>> Nice. Should these be initializers like: >>>>>>> >>>>>>> extension Int { >>>>>>> init(randomIn: Countable{Closed}Range<Int>) >>>>>>> } >>>>>>> >>>>>> >>>>>> I don’t see much of a case for making it it random(in: >>>>>> SpecificCollection) instead of genericCollection.random(). >>>>> >>>>> I see a couple points in favor of these static methods (or initializers) >>>>> on the numeric types: >>>>> >>>>> 1) The collection method will need to return an optional to match the >>>>> semantics of existing methods (like min()). If this is the only method >>>>> available, every time someone needs a random value in the range 1...10, >>>>> they’ll need to unwrap the result (with either force unwrapping, which >>>>> people will complain about, or some kind of conditional binding, which is >>>>> its own problem). Even if the semantics are the same (trapping on an >>>>> empty range), the user experience of using a non-optional method will be >>>>> better. >>>>> >>>>> 2) Floating-point ranges won’t get the collection method, so either we’ll >>>>> have inconsistent APIs (random FP value is non-optional, random integer >>>>> is optional) or we’ll make the FP API optional just to match. Both of >>>>> those seem bad. >>>>> >>>>>> One possible reason is if you exclude half-open ranges, only having >>>>>> CountableClosedRange, then you don’t have to account for the possibility >>>>>> of an empty collection (via an optional or a trap) because they cannot >>>>>> be empty. But closed ranges aren’t the currency type – half-open ranges >>>>>> are. So it’d hit usability if you have to convert from one to t'other >>>>>> often. >>>>>> >>>>>> Other possibility is discovery. But given the common use case is “random >>>>>> element from collection”, I don’t expect this to be an issue as it will >>>>>> quickly become common knowledge that this feature is available. >>>>> >>>>> Agreed here—I don’t think discovery is really an issue between the two >>>>> kinds. However, I don’t think the overlap in features (two ways to >>>>> generate random integers) are a problem, especially as we’d have better >>>>> alignment between integer and floating-point methods. >>>>> >>>>> Nate >>>>> _______________________________________________ >>>>> 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 >> >> _______________________________________________ >> 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
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution