Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

let v var has to do with mutable bindings, value mutability within the bindings should be a separate concern.

Rust makes that exact difference[-1]: `mut` can be used either at the binding level

    let mut a: ∫
or at the type level:

    let b: &mut int = &mut 1;
Both are references (~pointers) to an int, but `a` is a mutable reference, it can be changed to point to a new value[0]:

    a = &2;
because b is an immutable reference it can't point to a new value and

    b = &mut 2;
is a compilation error:

     error: re-assignment of immutable variable `b`
however b's value can be modified in place:

    *b += 1;
whereas trying that with a:

    *a += 1;
is an error:

    test.rs:5:5: 5:7 error: cannot assign to immutable dereference of `&`-pointer `*a`
`a` is a mutable reference to an immutable value, `b` is an immutable reference to a mutable value.

[-1] and so does C though it has the opposite defaults, you can have an

    int const *
— a mutable pointer to an immutable int (you can reassign the pointer but not change the pointee) — and an

    int * const
— an immutable pointer to a mutable int (you can't reassign the pointer but you can alter the pointee)

[0] the code does not work as-is because lifetimes, but close enough



I didn't appreciate that Rust makes that distinction, that really is quite elegant.

By way of comparison (to Rust and the original article), here is Scala:

    scala> val a = scala.collection.immutable.Set("apple", "orange")
    a: scala.collection.immutable.Set[String] = Set(apple, orange)

    scala> a = Set()
    <console>:8: error: reassignment to val
           a = Set()
             ^

    scala> val b = scala.collection.mutable.Set("cherry", "plum")
    b: scala.collection.mutable.Set[String] = Set(cherry, plum)

    scala> var c = b
    c: scala.collection.mutable.Set[String] = Set(cherry, plum)

    scala> b += "pear"
    res6: b.type = Set(pear, cherry, plum)

    scala> c
    res7: scala.collection.mutable.Set[String] = Set(pear, cherry, plum)

    scala> c = a
    <console>:10: error: type mismatch;
     found   : scala.collection.immutable.Set[String]
     required: scala.collection.mutable.Set[String]
           c = a
               ^
In other words: var versus val has to do with mutable bindings; mutable bindings allow you to mutate the value but not the type; object mutability within the bindings is governed by the object's own type (as the original author recommended for Swift).


The different types of mutability are also quite important for the concept of "borrowing" in Rust, which is simply taking a reference. The compiler ensures that ownership of the variable isn't transferred while any such reference is active, and only one mutable reference (of a mutable type) can exist at any one time. This means that bugs like that shown for Swift are impossible in Rust, because the language ensures no two things can ever modify it at the same time.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: