[swift-users] How to be DRY on ranges and closed ranges?

Nevin Brackett-Rozinsky nevin.brackettrozinsky at gmail.com
Wed Oct 12 18:54:43 CDT 2016


You could also create a “Range” protocol with “lowerBound” and “upperBound”
properties. Conform all the range types to it, and make your function take
generic over the protocol.

Nevin


On Wed, Oct 12, 2016 at 7:21 PM, Hooman Mehr via swift-users <
swift-users at swift.org> wrote:

> I recommend having explicit precondition and reducing repetition like this:
>
> import Foundation
>
> func random(from range: CountableRange<Int>) -> Int {
>
>     precondition(range.count > 0,
>                  "The range can't be empty.")
>
>     return random(from: CountableClosedRange(range))
> }
>
> func random(from range: CountableClosedRange<Int>) -> Int {
>
>     let lowerBound = range.lowerBound
>     let upperBound = range.upperBound
>
>     precondition(upperBound - lowerBound < Int(UInt32.max),
>                  "The range \(range) is too wide. It shouldn't be wider
> than \(UInt32.max).")
>
>     return lowerBound + Int(arc4random_uniform(UInt32(upperBound -
> lowerBound + 1)))
> }
>
> let r1 = random(from: 4 ..< 8)
> let r2 = random(from: 6 ... 8)
>
> Once we have the new improved Integer protocols
> <https://github.com/apple/swift-evolution/blob/master/proposals/0104-improved-integers.md> in
> place, you will be able to make it generic to support all integer types.
> (It is possible now, but too messy to be worth doing.)
>
>
> On Oct 12, 2016, at 1:23 PM, Adriano Ferreira via swift-users <
> swift-users at swift.org> wrote:
>
> Hi there!
>
> Ole Begeman offers here <https://oleb.net/blog/2016/09/swift-3-ranges/> (take
> a look at the bottom of the page) an interesting consideration about
> converting between half-open and closed ranges.
>
> As of now, it seems the way to go is by overloading…
>
>
> import Foundation
>
> func random(from range: Range<Int>) -> Int {
>     let lowerBound = range.lowerBound
>     let upperBound = range.upperBound
>
>     return lowerBound + Int(arc4random_uniform(UInt32(upperBound -
> lowerBound)))
> }
>
> func random(from range: ClosedRange<Int>) -> Int {
>     let lowerBound = range.lowerBound
>     let upperBound = range.upperBound
>
>     return lowerBound + Int(arc4random_uniform(UInt32(upperBound -
> lowerBound + 1)))
> }
>
> let r1 = random(from: 4 ..< 8)
> let r2 = random(from: 6 ... 8)
>
>
> Cheers,
>
> — A
>
> On Oct 12, 2016, at 6:21 AM, Jean-Denis Muys via swift-users <
> swift-users at swift.org> wrote:
>
> Hi,
>
> I defined this:
>
> func random(from r: Range<Int>) -> Int {
>     let from = r.lowerBound
>     let to =  r.upperBound
>
>     let rnd = arc4random_uniform(UInt32(to-from))
>     return from + Int(rnd)
> }
>
> so that I can do:
>
> let testRandomValue = random(from: 4..<8)
>
> But this will not let me do:
>
> let otherTestRandomValue = random(from: 4...10)
>
> The error message is a bit cryptic:
>
> “No ‘…’ candidate produce the expected contextual result type ‘Range<Int>’”
>
> What is happening is that 4…10 is not a Range, but a ClosedRange.
>
> Of course I can overload my function above to add a version that takes a
> ClosedRange.
>
> But this is not very DRY.
>
> What would be a more idiomatic way?
>
> Thanks,
>
> Jean-Denis
>
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
>
>
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
>
>
>
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20161012/6d069416/attachment.html>


More information about the swift-users mailing list