### 4` `Expression forms

#### 4.1` `Variable expressions

expr

var_name

The value of a variable, which must be a function parameter, bound with let, or defined with def. For example,

let x = 5 println('%p', x)

prints “5”.

Lexically, a variable is a letter or underscore, followed by zero or more letters, underscores, or digits, optionally ending in a question mark or exclamation point.

#### 4.2` `Literal expressions

expr

number

A numeric literal.

expr

string

A string literal.

expr

The true Boolean value.

expr

The false Boolean value.

This is one of only two values that are not considered truthy for the purpose of conditionals. The other non-truthy value is None.

expr

A special value for representing missing data. This is also the result of functions that are called just for their side effects, such as print.

This is one of only two values that are not considered truthy for the purpose of conditionals. The other non-truthy value is False.

#### 4.3` `Functions and application expressions

expr

Evaluates all the expressions; ⟨expr0⟩ must evaluate to a procedure. Then applies the result of ⟨expr0⟩ with the results of the other expressions as arguments.

For example,

fact(5)

calls the function fact with argument 5, and

ack(5 + 1, 5 + 2)

calls the function ack with arguments 6 and 7.

Note that method calls are just object method lookup combined with procedure applcation. That is, when you write

q.enqueue(5)

that means lookup the enqueue method in q, and then apply the result to 5.

expr

λ var_name1, ..., var_namek: ⟨simple⟩

Creates an anonymous function with parameters var_name1, ..., var_namek and body ⟨simple⟩. For example, the function to add twice its first argument to its second argument can be written

lambda x, y: 2 * x + y

#### 4.4` `Vectors and indexing expressions

expr

Expression ⟨expr1⟩ must evaluate to a vector or string o; ⟨expr2⟩ must evaluate to an integer n between 0 and o.len() - 1. Then this returns the nth element of vector o or the nth character of string o.

expr

Creates a new vector of length k whose values are the values of the expressions.

For example:

let v = [ 1, 2, 3, 4, 5 ]

expr

Constructs a new vector whose length is the value of ⟨exprsize⟩, filled with the value of ⟨exprinit⟩. That is,

[ 0; 5 ]

means the same thing as

[ 0, 0, 0, 0, 0 ]

Note that ⟨exprinit⟩ is not re-evaluated to produce each element, so an expression like [[0; 5]; 5] produces a vector that contains the same vector five times, not five different subvectors.

expr

Vector comprehensions: produces a vector of the values of ⟨exprelem⟩ while iterating the variable(s) over ⟨expriter⟩. In particular, ⟨expriter⟩ must be a vector v, a string s, or a natural number n; in which case the iterated-over values are the elements of v, the characters of s, or counting from 0 to n - 1, respectively. If one variable var_name is provided, it takes on those values. If two are provided, then var_name2 takes on those values, while var_name1 takes on the indices counting from 0 upward.

For example,

[ 10 * n for n in [ 5, 4, 3, 2, 1 ] ]

evaluates to

[ 50, 40, 30, 20, 10 ]

And

[ 10 * n + i for i, n in [ 5, 4, 3, 2, 1 ] ]

evaluates to

[ 50, 41, 32, 23, 14 ]

expr

[ ⟨exprelem⟩ for var_name1, var_name2 in ⟨expriter⟩ if ⟨exprcond⟩ ]

If the optional ⟨exprcond⟩ is provided, only elements for which ⟨exprcond⟩ is non-false are included. That is, the variable(s) take on each of their values, then ⟨exprcond⟩ is evaluated in the scope of the variable(s). If it’s non-false then ⟨exprelem⟩ is evaluated and included in the resulting vector.

For example,

[ 10 * n for n in [ 5, 4, 3, 2, 1 ] if odd?(n) ]

evaluates to

[ 50, 30, 10 ]

#### 4.5` `Structs and projection expressions

expr

⟨expr⟩.prop_name

Expression ⟨expr⟩ must evaluate to struct value that has field prop_name or an object value that has method prop_name; then this expression evaluates to the value of that field of the struct or that method of the object.

expr

struct_name { field_name1: ⟨expr1⟩, ..., field_namek: ⟨exprk⟩ }

Constructs a struct with the given name and the values of the given expressions for its fields. The struct must have been declared with those fields using struct.

If a variable with the same name as a field is in scope, omitting the field value will use that variable:

struct Foo: let bar let baz let bar = 4 let baz = 5 assert Foo { bar, baz: 9 } == Foo(4, 9)

#### 4.6` `Operator expressions

Operators are described in order from tighest to loosest precedence.

expr

Raises the value of ⟨expr1⟩ to the power of the value of ⟨expr2⟩, both of which must be numbers.

The ** operator is right-associative.

expr

-⟨expr⟩

+⟨expr⟩

Logical negation, bitwise negation, numerical negation, and numerical identity.

not ⟨expr⟩ evaluates ⟨expr⟩, then returns True if the result was False or None, and False for any other result.

~⟨expr⟩ requires that ⟨expr⟩ evalutes to an integer or Boolean; it flips every bit of the number, or negates the Boolean.

-⟨expr⟩ and +⟨expr⟩ require that ⟨expr⟩ evaluates to a number. Then - negates the number, and + returns it unchanged.

expr

Multiplies, divides, or modulos the values of the expressions, respectively.

expr

Addition:

Given two numbers, adds them.

Given two strings, concatenates them.

Given a string and another value, in any order, converts the other value to a string and concatenates them.

Anything else is an error.

expr

Subtracts two numbers.

expr

Left and right bitwise shift.

expr

Bitwise and for integers; logical and for Booleans.

expr

Bitwise xor for integers; logical xor for Booleans.

expr

Bitwise or for integers; logical or for Booleans. (Not written with the backslash.)

expr

Operator == is structural equality (except for classes that override it), and != is its negation. Operator is is physical equality, and |is not| (not written with the vertical bars) is its negation. To understand the difference, suppose that we create two different vectors with the same contents. Those vectors are structurally equal but not physically equal.

Operators <, <=, >, and >= are the standard inequalities for numbers and characters, and compare strings in lexicographic order.

expr

Short-circuiting logical and. First evaluates ⟨expr1⟩; if the result is False or None then the whole conjunction is False; otherwise, the result of the conjunction is the result of ⟨expr2⟩.

expr

Short-circuiting logical or. First evaluates ⟨expr1⟩; if the result is non-false then the whole disjunction has that result; otherwise the result of the disjunction is the result of ⟨expr2⟩.

expr

The ternary expression first evaluates the condition ⟨exprcond⟩. If non-false, evaluates ⟨exprthen⟩ for its value; otherwise, evaluates ⟨exprelse⟩ for its value.

For example:

def parent(link): link.parent if rbn?(link) else None