Looping through all values between UInt8.min and UInt8.max


#1

print(UInt8.min) //0

print(UInt8.max) //255

//Is there an easy way to loop between all values

//between (and including both) UInt8.min and UInt8.max?

//This doesn't work.

//Runtime crash because UInt8.max has no successor.

for i in UInt8.min...UInt8.max {

print\(i\)

}


(Erica Sadun) #2

Easy? No.

// Range Index has no valid successor
for i in UInt8.min ... UInt8.max {
    print(i)
}

// '...' cannot be applied to two 'UInt8' operands
for i in UInt8.min ... UInt8.max as ClosedInterval {
    print(i)
}

// Stops at 254
for i in UInt8.min ..< UInt8.max {
    print(i)
}

This works, but ugh:

for i : Int in numericCast(UInt8.min)...numericCast(UInt8.max) {
    guard let j: UInt8 = UInt8(i) else { fatalError("Nope") }
    print(j)
}

cc'ing in a few people to the white courtesy range phone.

-- E

···

On Apr 8, 2016, at 3:48 AM, tuuranton--- via swift-users <swift-users@swift.org> wrote:

print(UInt8.min) //0

print(UInt8.max) //255

//Is there an easy way to loop between all values

//between (and including both) UInt8.min and UInt8.max?

//This doesn't work.

//Runtime crash because UInt8.max has no successor.

for i in UInt8.min...UInt8.max {

    print(i)

}


(Erica Sadun) #3

It's a really good corner case to consider if you're thinking about redesigning ranges though. -- E

···

On Apr 8, 2016, at 8:43 AM, Nate Cook <natecook@gmail.com> wrote:

You can stride through the maximum value of a type if you land right on it:

for i in UInt8.min.stride(through: UInt8.max, by: 1) {
    print(i)
}

Nate


(Dmitri Gribenko) #4

Hi,

This works on the
https://github.com/apple/swift/tree/swift-3-indexing-model branch,
which we are about to send a proposal for.

Dmitri

···

On Fri, Apr 8, 2016 at 2:48 AM, tuuranton--- via swift-users <swift-users@swift.org> wrote:

print(UInt8.min) //0

print(UInt8.max) //255

//Is there an easy way to loop between all values

//between (and including both) UInt8.min and UInt8.max?

//This doesn't work.

//Runtime crash because UInt8.max has no successor.

for i in UInt8.min...UInt8.max {

    print(i)

}

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Nate Cook) #5

You can stride through the maximum value of a type if you land right on it:

for i in UInt8.min.stride(through: UInt8.max, by: 1) {
    print(i)
}

Nate

···

On Apr 8, 2016, at 9:21 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 8, 2016, at 3:48 AM, tuuranton--- via swift-users <swift-users@swift.org> wrote:

print(UInt8.min) //0

print(UInt8.max) //255

//Is there an easy way to loop between all values

//between (and including both) UInt8.min and UInt8.max?

//This doesn't work.

//Runtime crash because UInt8.max has no successor.

for i in UInt8.min...UInt8.max {

    print(i)

}

Easy? No.

// Range Index has no valid successor
for i in UInt8.min ... UInt8.max {
    print(i)
}

// '...' cannot be applied to two 'UInt8' operands
for i in UInt8.min ... UInt8.max as ClosedInterval {
    print(i)
}

// Stops at 254
for i in UInt8.min ..< UInt8.max {
    print(i)
}

This works, but ugh:

for i : Int in numericCast(UInt8.min)...numericCast(UInt8.max) {
    guard let j: UInt8 = UInt8(i) else { fatalError("Nope") }
    print(j)
}

cc'ing in a few people to the white courtesy range phone.

-- E


(Dave Abrahams) #6

Yes! It works in the swift-3-indexing-model branch.

···

on Fri Apr 08 2016, Erica Sadun <erica-AT-ericasadun.com> wrote:

    On Apr 8, 2016, at 3:48 AM, tuuranton--- via swift-users > <swift-users@swift.org> wrote:

        print(UInt8.min) //0

    print(UInt8.max) //255

        //Is there an easy way to loop between all values

    //between (and including both) UInt8.min and UInt8.max?

        //This doesn't work.

    //Runtime crash because UInt8.max has no successor.

    for i in UInt8.min...UInt8.max {

    print(i)

    }

Easy? No.

--
Dave


(Milos Rankovic) #7

Hi Erica,

Wouldn’t this work for @tuuranton’s purposes?

let allUInt8s = UInt8.min.stride(through: UInt8.max, by: 1)

allUInt8s.dynamicType // StrideThrough<UInt8>.Type

Array(allUInt8s).count // 256

for i in allUInt8s {
  i // 0...255
}

milos

···

On 8 Apr 2016, at 13:48, tuuranton--- via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

The problem with both solutions is that I lose the type information. Instead of i being UInt8 it is Int or UInt.

This is one solution I came up with:

extension UInt8 {
    static var allValues: [UInt8] {
        var v: [UInt8] = []
        for i in 0..<UInt8.max {
            v.append(i)
        }
        v.append(UInt8.max)
        return v
    }
}

print(UInt8.allValues)

In other words, loop from 0 to 254 and then add 255 manually at the end.

Is there currently no simpler way to do this in Swift?

Idea for the Swift developers: Create a Bounded protocol that UInt8 (and the other integer types) conform to. Then add a "allValues" type method in that protocol. And also put .min and .max into that protocol. Currently it seems like .min and .max are not a part of any particular protocol.

8. Apr 2016 14:35 by swift-users@swift.org <mailto:swift-users@swift.org>:

You could cast the min and max values to an Int and iterate through the Int range:

let min = Int(UInt8.min)
let max = Int(UInt8.max)

for i in min...max {
    print(i)
}

While this will work it seems like a hack to me and Milos’ solution is more elegant…

-Pete

On Apr 8, 2016, at 5:50 AM, tuuranton--- via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

I forgot to mention that I really would like to have i have type UInt8 within the loop. And since i is UInt8 it makes sense it should be able to take the values UInt8.min and UInt8.max (and all the values between).

8. Apr 2016 11:48 by swift-users@swift.org <mailto:swift-users@swift.org>:

print(UInt8.min) //0

print(UInt8.max) //255

//Is there an easy way to loop between all values

//between (and including both) UInt8.min and UInt8.max?

//This doesn't work.

//Runtime crash because UInt8.max has no successor.

for i in UInt8.min...UInt8.max {

    print(i)

}

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

On 8 Apr 2016, at 15:21, Erica Sadun via swift-users <swift-users@swift.org> wrote:

On Apr 8, 2016, at 3:48 AM, tuuranton--- via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

print(UInt8.min) //0

print(UInt8.max) //255

//Is there an easy way to loop between all values

//between (and including both) UInt8.min and UInt8.max?

//This doesn't work.

//Runtime crash because UInt8.max has no successor.

for i in UInt8.min...UInt8.max {

    print(i)

}

Easy? No.

// Range Index has no valid successor
for i in UInt8.min ... UInt8.max {
    print(i)
}

// '...' cannot be applied to two 'UInt8' operands
for i in UInt8.min ... UInt8.max as ClosedInterval {
    print(i)
}

// Stops at 254
for i in UInt8.min ..< UInt8.max {
    print(i)
}

This works, but ugh:

for i : Int in numericCast(UInt8.min)...numericCast(UInt8.max) {
    guard let j: UInt8 = UInt8(i) else { fatalError("Nope") }
    print(j)
}

cc'ing in a few people to the white courtesy range phone.

-- E

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users


(Xiaodi Wu) #8

Ouch. Yes, the upper bound can't be required to have a successor.

···

On Fri, Apr 8, 2016 at 3:45 PM Erica Sadun <erica@ericasadun.com> wrote:

It's a really good corner case to consider if you're thinking about
redesigning ranges though. -- E

> On Apr 8, 2016, at 8:43 AM, Nate Cook <natecook@gmail.com> wrote:
>
> You can stride through the maximum value of a type if you land right on
it:
>
> for i in UInt8.min.stride(through: UInt8.max, by: 1) {
> print(i)
> }
>
> Nate


(Daniel Strobusch) #9

Hi,
just as a side note, I filed a bug on this some time ago:

https://bugs.swift.org/browse/SR-1091

so let’s hope, this gets fixed in Swift3. Its really annoying and dangerous because the error is not recovered at compile time.

Daniel


(Cody Weaver) #10

I think an easy answer if I understand the question right is.

let a: UInt8 = UInt8.min
let b = UInt8 = UInt8.max

for c in a..<b {
   print(c)
}

···

On Fri, Apr 8, 2016 at 10:27 AM Daniel Strobusch via swift-users < swift-users@swift.org> wrote:

Hi,
just as a side note, I filed a bug on this some time ago:

https://bugs.swift.org/browse/SR-1091

so let’s hope, this gets fixed in Swift3. Its really annoying and
dangerous because the error is not recovered at compile time.

Daniel
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Daniel Strobusch) #11

I think excluding the upper bound (..<) does not address the problem correctly. The problem occurs on including the upper bound.

Consider the following simple program

#!/usr/bin/env swift

if let n: UInt8 = UInt8(Process.arguments[1])
{
    for i in 0...n
    {
        print (i)
    }
}

this program compiles and may even pass some testing. It will run correctly for all values except 255, for which it crashes. The problem is that no one knows how many of these cases we do have in current production code and tracking these issues down may be almost impossible.
I would say, the take home message for know is, don’t use 0…n (i.e. include the upper bound) unless you are sure that the upper bound cannot be equal to the max value of the type.

I have not checked out the Swift3 branch which should fix this. Currently, with Swift2.2 I think this is a serious issue.

Daniel

···

On 08.04.2016, at 19:47, Cody Weaver <codyleeweaver@gmail.com> wrote:

I think an easy answer if I understand the question right is.

let a: UInt8 = UInt8.min
let b = UInt8 = UInt8.max

for c in a..<b {
   print(c)
}

On Fri, Apr 8, 2016 at 10:27 AM Daniel Strobusch via swift-users <swift-users@swift.org> wrote:
Hi,
just as a side note, I filed a bug on this some time ago:

https://bugs.swift.org/browse/SR-1091

so let’s hope, this gets fixed in Swift3. Its really annoying and dangerous because the error is not recovered at compile time.

Daniel
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users