I’m a student who’s new in Swift.
While I’m studying about the Optional, I got curious about the keyword nil, so I tried some experiment with it. I’m using Swift version 5.5.
As you can see in the image below, if I assign nil to a optional variable (which I named ‘name’) and then print it with print(name) and print("(name)") (string interpolation), I got nil on the console in both cases. (Line 5, 9)
But when I print nil without the optional variable, which I printed it with print(nil) and print("(nil)"), I got an error on both cases. (Line 7, 11)
I expected them all to print out nil but they didn’t.
I really want to know the difference between those cases.
3
Answers
The error message in XCode tells you exactly what happens:
nil is not compatible with expected argument type Any
– theprint
function expects a non-nil argument, as does the string interpolation with()
,Interesting question actually. If you look at the Swift documentation:
Swift also introduces optional types, which handle the absence of a value. Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”.
So think of it as nil is the absence of some value. As an example if you have:
name
can either be a string value, or the absence of a string value.So it makes no sense to try and print nil explicitly since you already know that it’s the absence of a value, however, it makes sense to print
name
to check if it has a string value and in that case what it is, or if it has no string value.The issue is that
nil
isn’t just one single value, likenull
in Java/C#.nil
is syntactic sugar forOptional<Wrapped>.none
. There’s one different kind of value for every possibleWrapped
. E.g. there isOptional<Int>.none
andOptional<String>.none
, and you can’t assign from one to the other, because they’re unrelated types.When you use
nil
, the value of theWrapped
generic parameter is inferred from context, much like when you do:print
takes anAny
, so that doesn’t give any relevant contextual type information. When you sayprint(nil)
, it’s not clear what the typed ofWrapped
should be. You might not care (becauseOptional<Int>.none
andOptional<String>.none
both print "nil"), but the type system can’t leave it open ended, so it’s a type error.If you added contextual type information, it works, such as using a variable of a known type, or using a coercion: