Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does an exclamation mark mean in the Swift language?

The Swift Programming Language guide has the following example:

class Person {     let name: String     init(name: String) { self.name = name }     var apartment: Apartment?     deinit { println("\(name) is being deinitialized") } }  class Apartment {     let number: Int     init(number: Int) { self.number = number }     var tenant: Person?     deinit { println("Apartment #\(number) is being deinitialized") } }  var john: Person? var number73: Apartment?  john = Person(name: "John Appleseed") number73 = Apartment(number: 73)  //From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html) 

Then when assigning the apartment to the person, they use an exclamation point to "unwrap the instance":

john!.apartment = number73 

What does it mean to "unwrap the instance"? Why is it necessary? How is it different from just doing the following:

john.apartment = number73 

I'm very new to the Swift language. Just trying to get the basics down.


UPDATE:
The big piece of the puzzle that I was missing (not directly stated in the answers - at least not at the time of writing this) is that when you do the following:

var john: Person? 

that does NOT mean that "john is of type Person and it might be nil", as I originally thought. I was simply misunderstanding that Person and Person? are completely separate types. Once I grasped that, all of the other ?, ! madness, and the great answers below, made a lot more sense.

like image 703
Troy Avatar asked Jun 03 '14 14:06

Troy


People also ask

What are the question marks and an exclamation mark in Swift?

An implicitly unwrapped optional is defined with an exclamation mark instead of a question mark. The exclamation mark indicates that the name property of the Person class is defined as an implicitly unwrapped optional. Note that the print statement returns the value of name , not an optional.

What does exclamation mean in code?

Some programming and scripting languages also use exclamation points to indicate warnings and errors, as well as a method to identify a non-executable line of the code/statement. In UNIX scripting, the exclamation point is used for telling the operating system which application to use for running the script.

What causes exclamation?

Punctuation Marks Are Writing Conventions Exclamation marks make a sentence more exciting, emphatic or emotional. They serve a specific purpose when setting a sentence's tone.

What does extra exclamation point mean?

It is used to end a rhetorical question or a simultaneous question and exclamation. Some writers, then, began using multiple exclamation points as a logical outgrowth of the interbang and single exclamation mark to add even more emphasis to words, phrases, and sentences.


2 Answers

What does it mean to "unwrap the instance"? Why is it necessary?

As far as I can work out (this is very new to me, too)...

The term "wrapped" implies we should think of an Optional variable as a present, wrapped in shiny paper, which might (sadly!) be empty.

When "wrapped", the value of an Optional variable is an enum with two possible values (a little like a Boolean). This enum describes whether the variable holds a value (Some(T)), or not (None).

If there is a value, this can be obtained by "unwrapping" the variable (obtaining the T from Some(T)).

How is john!.apartment = number73 different from john.apartment = number73? (Paraphrased)

If you write the name of an Optional variable (eg text john, without the !), this refers to the "wrapped" enum (Some/None), not the value itself (T). So john isn't an instance of Person, and it doesn't have an apartment member:

john.apartment // 'Person?' does not have a member named 'apartment' 

The actual Person value can be unwrapped in various ways:

  • "forced unwrapping": john! (gives the Person value if it exists, runtime error if it is nil)
  • "optional binding": if let p = john { println(p) } (executes the println if the value exists)
  • "optional chaining": john?.learnAboutSwift() (executes this made-up method if the value exists)

I guess you choose one of these ways to unwrap, depending upon what should happen in the nil case, and how likely that is. This language design forces the nil case to be handled explicitly, which I suppose improves safety over Obj-C (where it is easy to forget to handle the nil case).

Update:

The exclamation mark is also used in the syntax for declaring "Implicitly Unwrapped Optionals".

In the examples so far, the john variable has been declared as var john:Person?, and it is an Optional. If you want the actual value of that variable, you must unwrap it, using one of the three methods above.

If it were declared as var john:Person! instead, the variable would be an Implicitly Unwrapped Optional (see the section with this heading in Apple's book). There is no need to unwrap this kind of variable when accessing the value, and john can be used without additional syntax. But Apple's book says:

Implicitly unwrapped optionals should not be used when there is a possibility of a variable becoming nil at a later point. Always use a normal optional type if you need to check for a nil value during the lifetime of a variable.

Update 2:

The article "Interesting Swift Features" by Mike Ash gives some motivation for optional types. I think it is great, clear writing.

Update 3:

Another useful article about the implicitly unwrapped optional use for the exclamation mark: "Swift and the Last Mile" by Chris Adamson. The article explains that this is a pragmatic measure by Apple used to declare the types used by their Objective-C frameworks which might contain nil. Declaring a type as optional (using ?) or implicitly unwrapped (using !) is "a tradeoff between safety and convenience". In the examples given in the article, Apple have chosen to declare the types as implicitly unwrapped, making the calling code more convenient, but less safe.

Perhaps Apple might comb through their frameworks in the future, removing the uncertainty of implicitly unwrapped ("probably never nil") parameters and replacing them with optional ("certainly could be nil in particular [hopefully, documented!] circumstances") or standard non-optional ("is never nil") declarations, based on the exact behaviour of their Objective-C code.

like image 75
Ashley Avatar answered Sep 21 '22 23:09

Ashley


Here is what I think is the difference:

var john: Person? 

Means john can be nil

john?.apartment = number73 

The compiler will interpret this line as:

if john != nil {     john.apartment = number73 } 

While

john!.apartment = number73 

The compiler will interpret this line as simply:

john.apartment = number73 

Hence, using ! will unwrap the if statement, and make it run faster, but if john is nil, then a runtime error will happen.

So wrap here doesn't mean it is memory wrapped, but it means it is code wrapped, in this case it is wrapped with an if statement, and because Apple pay close attention to performance in runtime, they want to give you a way to make your app run with the best possible performance.

Update:

Getting back to this answer after 4 years, as I got the highest reputations from it in Stackoverflow :) I misunderstood a little the meaning of unwrapping at that time. Now after 4 years I believe the meaning of unwrapping here is to expand the code from its original compact form. Also it means removing the vagueness around that object, as we are not sure by definition if it is nil or not. Just like the answer of Ashley above, think about it as a present which could contain nothing in it. But I still think that the unwrapping is code unwrapping and not memory based unwrapping as using enum.

like image 38
Amr Avatar answered Sep 20 '22 23:09

Amr