Skip to content

Commit

Permalink
Add example of constant with deferred assignment (#172)
Browse files Browse the repository at this point in the history
Fixes: #139
Fixes: rdar://114058607
  • Loading branch information
amartini51 authored Oct 16, 2023
2 parents 0a29526 + 0a57490 commit 54b2b2f
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 4 deletions.
5 changes: 5 additions & 0 deletions Style.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ Spelled as two words, not closed up or hyphenated.

See entry for *Swift*.

## definite initialization

Not “definitive initialization”.
Don‘t abbreviate as DI.

## function

In the reference,
Expand Down
58 changes: 54 additions & 4 deletions TSPL.docc/LanguageGuide/TheBasics.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,60 @@ because the maximum value never changes.
The current login attempt counter is declared as a variable,
because this value must be incremented after each failed login attempt.

If a stored value in your code won't change,
always declare it as a constant with the `let` keyword.
Use variables only for storing values that change.

When you declare a constant or a variable,
you can give it a value as part of that declaration,
like the examples above.
Alternatively,
you can assign its initial value later in the program,
as long as it's guaranteed to have a value
before the first time you read from it.

```swift
var environment = "development"
let maximumNumberOfLoginAttempts: Int
// maximumNumberOfLoginAttempts has no value yet.

if environment == "development" {
maximumNumberOfLoginAttempts = 100
} else {
maximumNumberOfLoginAttempts = 10
}
// Now maximumNumberOfLoginAttempts has a value, and can be read.
```

<!--
- test: `constantsWithDeferredInitialization`
```swifttest
-> var environment = "development"
-> let maximumNumberOfLoginAttempts: Int
-> if environment == "development" {
maximumNumberOfLoginAttempts = 100
} else {
maximumNumberOfLoginAttempts = 10
}
>> print(maxNumberOfLoginAttempts)
<< 100
```
-->

In this example,
the maximum number of login attempts is constant,
and its value depends on the environment.
In the development environment,
it has a value of 100;
in any other environment, its value is 10.
Both branches of the `if` statement
initialize `maximumNumberOfLoginAttempts` with some value,
guaranteeing that the constant always gets a value.
For information about how Swift checks your code
when you set an initial value this way,
see <doc:Declarations#Constant-Declaration>.

You can declare multiple constants or multiple variables on a single line,
separated by commas:

Expand All @@ -99,10 +153,6 @@ var x = 0.0, y = 0.0, z = 0.0
```
-->

> Note: If a stored value in your code won't change,
> always declare it as a constant with the `let` keyword.
> Use variables only for storing values that need to be able to change.
### Type Annotations

You can provide a *type annotation* when you declare a constant or variable,
Expand Down
21 changes: 21 additions & 0 deletions TSPL.docc/ReferenceManual/Declarations.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,24 @@ as long as it's guaranteed to have a value set
before the first time its value is read.
If the compiler can prove that the constant's value is never read,
the constant isn't required to have a value set at all.
This analysis is called *definite initialization* ---
the compiler proves that a value is definitely set before being read.

> Note:
> Definite initialization
> can't construct proofs that require domain knowledge,
> and its ability to track state across conditionals has a limit.
> If you can determine that constant always has a value set,
> but the compiler can't prove this is the case,
> try simplifying the code paths that set the value,
> or use a variable declaration instead.
<!--
In the most general case,
DI reduces to the halting problem,
as shown by Rice's theorem.
-->

When a constant declaration occurs in the context of a class or structure
declaration, it's considered a *constant property*.
Constant declarations aren't computed properties and therefore don't have getters
Expand Down Expand Up @@ -277,6 +295,9 @@ That said, if no initializer *expression* is present,
the variable declaration must include an explicit type annotation (`:` *type*).

As with constant declarations,
if a variable declaration omits the initializer *expression*,
the variable must have a value set before the first time it is read.
Also like constant declarations,
if the *variable name* is a tuple pattern,
the name of each item in the tuple is bound to the corresponding value
in the initializer *expression*.
Expand Down

0 comments on commit 54b2b2f

Please sign in to comment.