> On 6 Oct 2017, at 06:25, David Hart via swift-evolution 
> <[email protected]> wrote:
> 
> 
> 
>> On 5 Oct 2017, at 20:23, Ben Cohen via swift-evolution 
>> <[email protected]> wrote:
>> 
>> 
>>> On Oct 5, 2017, at 10:58, Nate Cook via swift-evolution 
>>> <[email protected]> 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?

I want to be able to check for empty at the same time as I get the value, 
exactly like I do first first and last:

if let rand = array.randomElement() {
    // use rand
} else {
    // handle empty
}

OR

guard let rand = array.randomElement() else {
    // handle empty
}

I also like those optional returning properties because it’s a small reminder 
from the type system to check for the corner case (empty) and makes them 
explicit when reading code. With a trapping function, I would often forget to 
handle empty and it wouldn’t jump out at me when reading code.

>> 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 <[email protected]> 
>>>> 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 
>>>> <[email protected]> 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 
>>>>> <[email protected]> escribió:
>>>>> 
>>>>>>> On Oct 5, 2017, at 11:30 AM, Ben Cohen via swift-evolution 
>>>>>>> <[email protected]> wrote:
>>>>>>> 
>>>>>>>> On Oct 4, 2017, at 9:12 PM, Chris Lattner via swift-evolution 
>>>>>>>> <[email protected]> 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
>>>>>> [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
> _______________________________________________
> 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

Reply via email to