3

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)

enter image description here

I expected them all to print out nil but they didn't. I really want to know the difference between those cases.

3 Answers3

6

The issue is that nil isn't just one single value, like null in Java/C#.

nil is syntactic sugar for Optional<Wrapped>.none. There's one different kind of value for every possible Wrapped. E.g. there is Optional<Int>.none and Optional<String>.none, and you can't assign from one to the other, because they're unrelated types.

When you use nil, the value of the Wrapped generic parameter is inferred from context, much like when you do:

let a = Optional<Int>.none           // most explicit
let b: Optional<Int> = Optional.none // Generic Wrapped param inferred from the type annotation
let c: Optional<Int> = nil           // Same inference

print takes an Any, so that doesn't give any relevant contextual type information. When you say print(nil), it's not clear what the typed of Wrapped should be. You might not care (because Optional<Int>.none and Optional<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:

print(nil as String?)
Alexander
  • 59,041
  • 12
  • 98
  • 151
2

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:

var name: String?

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.

bjorn.lau
  • 774
  • 5
  • 16
  • 1
    "The print function is telling you that you never just want to work with nil, and it makes no sense to print it explicitly, so the compiler prevents you from doing it." That's not why, and this isn't limited to just the `print` function. It'll happen in any other context where there's no contextual type information, like `let a = nil`. See my answer: https://stackoverflow.com/a/75324998/3141234 – Alexander Feb 02 '23 at 14:57
  • 1
    Agreed. The thinking here is reasonable, but it's simply incorrect. You can explore this by creating another function `func dothing(_ :Any) {}` and try to call it as `dothing(nil)`. You'll get the same error. The usefulness or lack of usefulness of printing doesn't matter here. – Rob Napier Feb 02 '23 at 15:48
  • Hehe, kind of knew this was coming, because yes you are totally correct! I just thought it was a bit easier to explain it this way even though it’s of course not 100% what’s going on. I should probably have put a disclaimer about that. Thanks for pointing it out. – bjorn.lau Feb 02 '23 at 23:08
0

The error message in XCode tells you exactly what happens: nil is not compatible with expected argument type Any - the print function expects a non-nil argument, as does the string interpolation with \(),

TheEye
  • 9,280
  • 2
  • 42
  • 58
  • 1
    "the print function expects a non-nil argument" That's not quite true. It can handle `nil` fine, but to have a valid `nil` value, you need to know the specific type it should be. See my answer https://stackoverflow.com/a/75324998/3141234 – Alexander Feb 02 '23 at 19:18
  • you are correct – TheEye Feb 03 '23 at 15:57