Why Any is so difficult for understanding?

Well in Any we can wrap any . But why we can't assign nil in Any directly, but we can indirectly in this way.

var a: Any
a = nil // Nil cannot be assigned to type 'Any'
var z: Int? = 0
a = z
z = nil
a = z // a is nil

Why we have regular Any and optional 'Any?' . Why we can't use regular any instead of optional any everywhere? I will be grateful for articles about this topic.

nil is syntactic sugar for Optional<T>.none. Compiler doesn't know what is T on the second line of your example. For example it could be Int? or String? or something else.

1 Like

Yes. So the Any behavior forces to define every optional type as
var z: Optional<Int> = 0. I understand that Swift has not nil at all. But the Any? case broke this clarity concept a little bit.

Idiomatic Swift would be

var z: Int? = 0

nil is a literal & only a type that conforms to ExpressibleByNilLiteral can be initialised with nil and since Any does not conform to that protocol, it cannot be initialised with nil. The only type that does is Optional. So, you can either do:

let a: Any? = Optional.none // Any? is sugar for Optional<Any>
let a: Any? = nil // Any? is sugar for Optional<Any>

or

let a: Optional<Any> = .none
let a: Optional<Any> = nil
2 Likes

We can:

let x = nil as Int? as Any

Nice, although this isn't a direct assignment as it's going though two levels of coercion. nil to Int? and then Int? to Any.

Wow, REPL has own opinion on it
07

The value of x is nil (or Optional<Int>.none) however the type is Any. This is because the value (Int? or Optional<Int>.none) is getting type-erased to Any. The reason why the value is nil (or Optional<Int>.none) is because of the initial coercion of nil to Int?, so you get Optional<Int>.none.

How to retrieve the Optional from Any now?

 let z: Any = Optional<Int>.none
    if let d = z as? Int? {  // Cannot downcast from 'Any' to a more optional type 'Int?'
        print(d)
    }

May be this operation does not have sense?

That looks like a bug, and I have created a thread here to discuss it.

My understanding and expectation is that it should be possible to cast an Any back to the type it wraps, so I am glad you called attention to the fact that it is not currently possible when that type is Optional.

I think is not bug, I think is kind of bad practice. But in my work I meet casting from Any? all time :( And I do not understand why the compiler warning disappear when we print optional value like
print("(myOptioanal as Any)")

The warning is only there to stop people from accidentally printing things like “Optional(42)” when they meant to print just the number. Print takes a variable number of Any arguments, so manually casting to Any just tells the compiler that, yes, you really wanted to print the Optional.

2 Likes

Every type in Swift implicitly is a subtype of Any. Any can be anything, it does not imply that the type behind Any is an Optional, therefore assigning nil to it does not make much sense. You can take any type instance and up-cast it to Any, or in other words erase all the type information you had to nothing.