skip to Main Content

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

Answers


  1. 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 (),

    Login or Signup to reply.
  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.

    Login or Signup to reply.
  3. 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?)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search