0

I have tried the following code, I can cast to Array as the type parameter.

let x: Array = [21,43,12]
let z: Any = x
if let arr = x as? Array<Any>{
    print("yes") // print "yes"
}

but why the following code doesn't work at all:

struct Base<T>{
    let val: T
    init(_ val: T){
        self.val = val
    }
}
let y = Base(7)
let an: Any = y
if let temp = an as? Base<Any> {
    print("yes") // the line won't print.
}

is it a bug?

and is it possible to do like that:

let arr = [232,32,55]
let x: Any = arr
if x is Array { // error.
    print("yes") // won't work. is any way to make it work?
} 
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Carl Hung
  • 545
  • 4
  • 17
  • Compare https://stackoverflow.com/q/41976844/2976878 – Hamish Jan 08 '18 at 22:24
  • no, it is different question. mine, I didn't cast to [Any]. I casted to Any – Carl Hung Jan 08 '18 at 22:33
  • 1
    @CarlHung I don't understand your comment. Where did you "cast to Any"? The problem is that `Base` is not the same thing as `Base`. I'd kind of like to mark this a dupe of Hamish's linked answer, but if it's enough different, @Hamish may be able to write a more targeted version of his answer. – Rob Napier Jan 08 '18 at 22:35
  • 2
    The second question ("and is it possible…") is a different question, and the answer is "no, Swift lacks higher-kinded types" which is the feature you'd need to make that work. You can't discuss "Array" without talking about what that Array holds. (That said, this kind of code, and particularly the use of `Any`, is often a sign of a design mistake in Swift, and when not a mistake, usually is the result of trying to make code more generic than is actually required, which Swift is not ready for.) – Rob Napier Jan 08 '18 at 22:37
  • array is just a generic struct. this generic struct `array`, the example, I casted to Any then I casted again to Array and the condition worked. – Carl Hung Jan 08 '18 at 22:38
  • 1
    Right; that's the point of Hamish's answer. `Array` gets special covariance handling in Swift that isn't available for user types. Note that Swift doesn't "cast" in this case. It actually converts (requiring a copy operation) the array from one type to the other via the `as?`. This piece of magic can be confusing. – Rob Napier Jan 08 '18 at 22:39
  • 1
    In you first issue Base(7) is actually Base(7) so in that case T is of type Int but Base is where T is of type Any it does not mean T can be of any Type (e.g. Int, Double, String, etc) it must explicitly be Any. Your test fails because Base is not the same as Base. – Upholder Of Truth Jan 08 '18 at 22:45
  • 1
    @RobNapier so basically, you are telling me that array, set and dictionary are provided special treatment? that the other types can' t do that? – Carl Hung Jan 08 '18 at 22:52
  • @RobNapier I didn't initially mark this as a dupe due to OP's additional question about `is Array`, but now you've answered that, I'm happy to do so (unless you want to write your own answer, that is). – Hamish Jan 08 '18 at 22:53
  • 1
    @CarlHung That's correct; the type checker recognises that arrays, sets and dictionaries can be converted to different element types as a special case. For a conditional array cast, at runtime the stdlib's [`_arrayConditionalCast`](https://github.com/apple/swift/blob/master/stdlib/public/core/ArrayCast.swift#L85) is called, which you can see just does `as?` casting on each of the elements, stopping on one of the casts failing. – Hamish Jan 08 '18 at 22:57

0 Answers0