Value assignments to variables use the = symbol.

let foo = 42;

bar = 123 * 456 - 789;

x[1][2].prop = do_calculation();

Valid Assignment Targets

The left-hand-side (LHS) of an assignment statement must be a valid l-value, which must be rooted in a variable, potentially extended via indexing or properties.

Assigning to invalid l-value

Expressions that are not valid l-values cannot be assigned to.

x = 42;                 // variable is an l-value

x[1][2][3] = 42         // variable indexing is an l-value

x.prop1.prop2 = 42;     // variable property is an l-value

foo(x) = 42;            // syntax error: function call is not an l-value = 42;           // syntax error: method call is not an l-value

(x + y) = 42;           // syntax error: binary op is not an l-value

Values are Cloned

Values assigned are always cloned. So care must be taken when assigning large data types (such as arrays).

x = y;                  // value of 'y' is cloned

x == y;                 // both 'x' and 'y' hold different copies
                        // of the same value

Moving Data

When assigning large data types, sometimes it is desirable to move the data instead of cloning it.

Use the take function (defined in the LangCorePackage but excluded when using a raw Engine) to move data.

The original variable is left with ()

x = take(y);            // value of 'y' is moved to 'x'

y == ();                // 'y' now holds '()'

x != y;                 // 'x' holds the original value of 'y'

Return large data types from functions

take is convenient when returning large data types from a function.

fn get_large_value_naive() {
    let large_result = do_complex_calculation();

    large_result.done = true;

    // Return a cloned copy of the result, then the
    // local variable 'large_result' is thrown away!

fn get_large_value_smart() {
    let large_result = do_complex_calculation();

    large_result.done = true;

    // Return the result without cloning!
    // Method style call is also OK.

Assigning large data types to object map properties

take is useful when assigning large data types to object map properties.

let x = [];

// Build a large array
for n in 0..1000000 { x += n; }

// The following clones the large array from 'x'.
// Both 'my_object.my_property' and 'x' now hold exact copies
// of the same large array!
my_object.my_property = x;

// Move it to object map property via 'take' without cloning.
// 'x' now holds '()'.
my_object.my_property = x.take();

// Without 'take', the following must be done to avoid cloning:
my_object.my_property = [];

for n in 0..1000000 { my_object.my_property += n; }