1

Hello guys I'm new here and right now I'm learning Swift by coding some fancy algorithms, which comes to my mind while reading Apples Swift book.

I was trying to compress (automatically downcast) any IntegerType value. Here is a little snippet of my Code which almost works fine except for one case:

switch signedValue
{
case Int64(Int8.min)...Int64(Int8.max):          compressedValue = Int8(signedValue)
case (Int64(Int8.max) + 1)...Int64(UInt8.max):   compressedValue = UInt8(signedValue)
case Int64(Int16.min)...Int64(Int16.max):        compressedValue = Int16(signedValue)
case (Int64(Int16.max) + 1)...Int64(UInt16.max): compressedValue = UInt16(signedValue)
case Int64(Int32.min)...Int64(Int32.max):        compressedValue = Int32(signedValue)
case (Int64(Int32.max) + 1)...Int64(UInt32.max): compressedValue = UInt32(signedValue)
case Int64(Int.min)...Int64(Int.max):            compressedValue = Int(signedValue) // range bug #1 - workaround '..<'
default:                                         compressedValue = signedValue
}

Assume signedValue is of Type Int64 and the input value is = 10_000_000_000. This will lead to a runtime error (in Playground):

Execution was interrupted, reason: EXC_BAD_INSTRUCTION ...

Could anyone help me out to understand what exactly is happening here. There is an workaround for this problem. Instead of '...' I could use '..<' but this not how the range should be.

DevAndArtist
  • 4,971
  • 1
  • 23
  • 48

2 Answers2

3

Unlike intervals (which have two flavours, half-open or closed), Range is only ever half-open. So when you write 1...5, the ...function increments the right-hand argument in order to create a half-open range 1..<6.

The consequence of this is you can’t have a range that spans the entire length of an integer type, since 1...Int.max will result in an attempt to increment Int.max, and an overflow error. You get a similar error with let s = "hello"; let r = s.startIndex...s.endIndex

All is not lost, however, since you shouldn’t be using ranges anyway, this is a job for ClosedInterval. Since the ... operator is used for both, and defaults to ranges (for overloading precedence reasons) you need to explicitly identify the type:

let i64interval: ClosedInterval = Int64(Int64.min)...Int64(Int64.max)
switch signedValue {
    // etc
    case i64interval:   compressedValue = Int(signedValue)
    default:            compressedValue = signedValue
}
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
  • Thx this helped. I wasn't done reading the book and didn't know about 'ClosedInterval' until now. Btw. it is also possible to write "case Int64(Int64.min)...Int64(Int64.max) as ClosedInterval:" to solve my problem. – DevAndArtist Feb 16 '15 at 17:40
3

Look at the documentation for the Range Type. It has the following little nugget of information that I never noticed before:

if T has a maximal value, it can serve as an endIndex, but can never be contained in a Range.

T, in that quote, is the type of value in the Range. So if you have a Range of Ints, the max value of the Int cannot be contained in the Range.

That's why it works if you put the ..< in there, instead of ....

Good question, by the way...

Aaron Rasmussen
  • 13,082
  • 3
  • 42
  • 43
  • Great, I will keep this in mind. I should probably check the docs before asking, but I do not understand every Xcode error, so I could find the problem by myself. – DevAndArtist Feb 16 '15 at 17:45
  • I find that website really helpful cuz its so easy to look things up by type, protocol, etc. Also, if you haven't discovered it yet, if you type `import Swift` into a playground and then command-click on `Swift`, you basically get the bulk of what is publicly available of Apple's Swift documentation. – Aaron Rasmussen Feb 16 '15 at 19:06
  • Do we actually need 'import Swift' for anything? Command-click on Int or any other Swift type will result the same. For the documentation part I'm using the free version of "Dash". Ok we should let it be as is, thx. I don't know if comments on here are allowed to be a little off topic. – DevAndArtist Feb 16 '15 at 19:14