Max Yankov
Max Yankov

Reputation: 13297

How exactly does the "let" keyword work in Swift?

I've read this simple explanation in the guide:

The value of a constant doesn’t need to be known at compile time, but you must assign it a value exactly once.

But I want a little more detail than this. If the constant references an object, can I still modify its properties? If it references a collection, can I add or remove elements from it? I come from a C# background; is it similar to how readonly works (apart from being able to use it in method bodies), and if it's not, how is it different?

Upvotes: 28

Views: 30374

Answers (6)

wcochran
wcochran

Reputation: 10896

It's best to think of let in terms of Static Single Assignment (SSA) -- every SSA variable is assigned to exactly once. In functional languages like lisp you don't (normally) use an assignment operator -- names are bound to a value exactly once. For example, the names y and z below are bound to a value exactly once (per invocation):

func pow(x: Float, n : Int) -> Float {
  if n == 0 {return 1}
  if n == 1 {return x}
  let y = pow(x, n/2)
  let z = y*y
  if n & 1 == 0 {
    return z
  }
  return z*x
}

This lends itself to more correct code since it enforces invariance and is side-effect free.

Here is how an imperative-style programmer might compute the first 6 powers of 5:

var powersOfFive = Int[]()
for n in [1, 2, 3, 4, 5, 6] {
    var n2 = n*n
    powersOfFive += n2*n2*n
}

Obviously n2 is is a loop invariant so we could use let instead:

var powersOfFive = Int[]()
for n in [1, 2, 3, 4, 5, 6] {
    let n2 = n*n
    powersOfFive += n2*n2*n
}

But a truly functional programmer would avoid all the side-effects and mutations:

let powersOfFive = [1, 2, 3, 4, 5, 6].map(
    {(num: Int) -> Int in
        let num2 = num*num
        return num2*num2*num})

Upvotes: 6

MD TAREQ HASSAN
MD TAREQ HASSAN

Reputation: 1276

First of all, "The let keyword defines a constant" is confusing for beginners who are coming from C# background (like me). After reading many Stack Overflow answers, I came to the conclusion that

Actually, in swift there is no concept of constant

A constant is an expression that is resolved at compilation time. For both C# and Java, constants must be assigned during declaration:

public const double pi = 3.1416;         // C#
public static final double pi = 3.1416   // Java

Apple doc ( defining constant using "let" ):

The value of a constant doesn’t need to be known at compile time, but you must assign the value exactly once.

In C# terms, you can think of "let" as "readonly" variable

Swift "let" == C# "readonly"

Upvotes: 3

d.danailov
d.danailov

Reputation: 9800

Swift properties:

Swift Properties official documentation

In its simplest form, a stored property is a constant or variable that is stored as part of an instance of a particular class or structure. Stored properties can be either variable stored properties (introduced by the varkeyword) or constant stored properties (introduced by the let keyword).

Example:

The example below defines a structure called FixedLengthRange, which describes a range of integers whose range length cannot be changed once it is created:

struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}

Instances of FixedLengthRange have a variable stored property called firstValue and a constant stored property called length. In the example above, length is initialized when the new range is created and cannot be changed thereafter, because it is a constant property.

Upvotes: 0

rickster
rickster

Reputation: 126127

let is a little bit like a const pointer in C. If you reference an object with a let, you can change the object's properties or call methods on it, but you cannot assign a different object to that identifier.

let also has implications for collections and non-object types. If you reference a struct with a let, you cannot change its properties or call any of its mutating func methods.

Using let/var with collections works much like mutable/immutable Foundation collections: If you assign an array to a let, you can't change its contents. If you reference a dictionary with let, you can't add/remove key/value pairs or assign a new value for a key — it's truly immutable. If you want to assign to subscripts in, append to, or otherwise mutate an array or dictionary, you must declare it with var.

(Prior to Xcode 6 beta 3, Swift arrays had a weird mix of value and reference semantics, and were partially mutable when assigned to a let -- that's gone now.)

Upvotes: 48

StaticReturn
StaticReturn

Reputation: 49

Let


Swift uses two basic techniques to store values for a programmer to access by using a name: let and var. Use let if you're never going to change the value associated with that name. Use var if you expect for that name to refer to a changing set of values.

let a = 5  // This is now a constant. "a" can never be changed.
var b = 2  // This is now a variable. Change "b" when you like.

The value that a constant refers to can never be changed, however the thing that a constant refers to can change if it is an instance of a class.

let a = 5
let b = someClass()
a = 6  // Nope.
b = someOtherClass()  // Nope.
b.setCookies( newNumberOfCookies: 5 )  // Ok, sure.

Let and Collections


When you assign an array to a constant, elements can no longer be added or removed from that array. However, the value of any of that array's elements may still be changed.

let a = [1, 2, 3]
a.append(4)  // This is NOT OK. You may not add a new value.
a[0] = 0     // This is OK. You can change an existing value.

A dictionary assigned to a constant can not be changed in any way.

let a = [1: "Awesome", 2: "Not Awesome"]
a[3] = "Bogus"             // This is NOT OK. You may not add new key:value pairs.
a[1] = "Totally Awesome"   // This is NOT OK. You may not change a value.

That is my understanding of this topic. Please correct me where needed. Excuse me if the question is already answered, I am doing this in part to help myself learn.

Upvotes: 4

Asik
Asik

Reputation: 22133

F# users will feel right at home with Swift's let keyword. :)

In C# terms, you can think of "let" as "readonly var", if that construct was allowed, i.e.: an identifier that can only be bound at the point of declaration.

Upvotes: 0

Related Questions