3

Why is the type cast operator (as) being used instead of its conditional form (as?) in this switch statement?

I thought the type operator could only be (as?) or (as!)...? The Apple Swift documentation does not provide adequate explanation about this.

Here is the example in the Swift documentation:

var things = [Any]()

things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append((3.0, 5.0))
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
things.append({ (name: String) -> String in "Hello, \(name)" }) 

for thing in things {
        switch thing {
        case 0 as Int:
            println("zero as an Int")
        case 0 as Double:
            println("zero as a Double")
        case let someInt as Int:
            println("an integer value of \(someInt)")
        case let someDouble as Double where someDouble > 0:
            println("a positive double value of \(someDouble)")
        case is Double:
            println("some other double value that I don't want to print")
        case let someString as String:
            println("a string value of \"\(someString)\"")
        case let (x, y) as (Double, Double):
            println("an (x, y) point at \(x), \(y)")
        case let movie as Movie:
            println("a movie called '\(movie.name)', dir. \(movie.director)")
        case let stringConverter as String -> String:
            println(stringConverter("Michael"))
        default:
            println("something else")
        }
    }

Here is the link to the Apple Swift documentation on Type Casting

Walter M
  • 4,993
  • 5
  • 22
  • 29
  • Put up an interesting example for "case is" i.e, "case is Int, is String". Refer to http://stackoverflow.com/questions/25724527/swift-test-class-type-in-switch-statement/32497118#32497118 – Abhijeet Sep 10 '15 at 08:58

3 Answers3

4

You could have found the answer yourself if you read the note on the bottom:

The cases of a switch statement use the forced version of the type cast operator (as, not as?) to check and cast to a specific type. This check is always safe within the context of a switch case statement.

(emphasis mine)

Here is an Apple blog post which elaborates on the difference between as?, as and as!.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
  • 1
    That same documentation also refers to "forced version of the type cast operator" to be "`(as!)`" in many different locations within the document, so I can understand Walter's confusion. – Michael Dautermann Aug 01 '15 at 08:24
  • Yes I have read that note. That note says "forced version of the type cast operator" which is **a!**. It doesn't explain why the exclamation mark (!) is not included. Also, your reference explains that **as** is a guaranteed conversion. I am not sure what that means. The Swift documentation only explains **as?** and **as!**. – Walter M Aug 01 '15 at 10:33
  • 1
    The ! is not included because a runtime error can never occur - the `case` statement *guarantees* that if the `thing` is not an `Int`, the casting is not performed. I agree with you that it is confusing, though. – Glorfindel Aug 01 '15 at 10:37
  • @Glorfindel thank you! thats what I was wondering :). In my opinion, Apple made this documentation too concise that it just ends up leaving people, like me, wondering. Thank you for taking the time to answer my question :) – Walter M Aug 01 '15 at 10:44
1

The as in case 0 as Int: or case let someInt as Int: is part of a type casting pattern. In the Swift Language Reference the case label of a switch statement is defined as

case-labelcase ­case-item-list­:
­case-item-list → pattern ­guard-clause­opt |­ pattern­ guard-clause­­opt­ , ­case-item-list­

where pattern can be (among other cases)

pattern → value-binding-pattern­
pattern → type-casting-pattern­
pattern → expression-pattern­

and a type casting pattern is

type-casting-pattern → is-pattern­ | as-pattern­
is-patternis ­type­
as-pattern → pattern­ as ­type­

So you have for example

case let someInt as Int:
╰──────────────────────╯ case-label
     ╰────────────────╯  case-item-list -> type-casting pattern
                    ╰─╯  type
                 ╰╯      `as` keyword
     ╰─────────╯         value-binding pattern
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
0

Swift-Blog:

It may be easiest to remember the pattern for these operators in Swift as: ! implies “this might trap,” while ? indicates “this might be nil.”

And there is the third possibility of a guaranteed conversion, when an upcast is done. For example 2 as Any gets a warning when used with as! or as?

In case of the switch construct, the case let value as Type: never fails nor is there the possibility, that value will be an optional type in contrast to the expression value as? Type

heiko
  • 1,268
  • 1
  • 12
  • 20