Chapter 2

Syntax

Expressions

An expression is a construct that is executed for the values it returns and/or the side-effects that it performs. The active portions of a Dylan program are expressions. An expression is either a literal constant, a named value reference, a function call, a unary operator call, a binary operator call, an element reference, a slot reference, a parenthesized expression, or a statement.

An operand is a restricted expression: it cannot be a unary or binary operator call nor a symbol literal. The other seven forms of expression are allowed. Operands appear in situations in the grammar where an expression is desirable but the full generality of expressions would make the grammar ambiguous.

A literal constant directly represents an object. Literal constants are available for numbers, characters, strings, symbols, boolean values, pairs, lists, and vectors. For example:

number

123, 1.5, -4.0, #x1f4e

character

'a', '\n'

string

"foo", "line 1\nline 2"

symbol

test:, #"red"

boolean value

#t, #f

pair

#(1 . "one")

list

#(1, 2, 3)

vector

#[1, 2, 3]

Literal constants are immutable. Attempting to modify an immutable object has undefined consequences. Immutable objects may share structure. Literal constants that are equal may or may not be identical.

A symbol can be indicated in two ways: as a keyword (for example, test:) or as a unique string (for example, #"red"). The difference is purely syntactic; the choice is provided to promote program readability.

A string literal can be broken across lines by writing two string literals in a row, separated only by whitespace; they are automatically concatenated (without a newline character).

A named value reference returns the value of a visible binding given its name; for example, foo. The referenced binding can be a module binding (either constant or variable) or a local binding established by a local declaration or by a parameter list. The value of the binding must not be a macro.

A reserved word is a syntactic token that has the form of a name but is reserved by the Dylan language and so cannot be given a binding and cannot be used as a named value reference. There are seven reserved words in Dylan: define, end, handler, let, local, macro, and otherwise.

A function call applies a function to arguments, and returns whatever values the function returns. The function is indicated by an operand and can be a generic function, a method, or a function macro. The arguments are separated by commas and enclosed in parentheses. For example, f(x, y). For readability, the comma can be omitted between the two arguments in a keyword/value pair, for example element(c, k, default: d) is a function call with four arguments.

A unary operator call consists of an operand preceded by one of the two unary operators: - (arithmetic negation) or ~ (logical negation); for example, - x. A unary operator call is actually an abbreviated notation for a function call.

A binary operator call consists of two expressions separated by one of the binary operators: + (addition), - (subtraction), * (multiplication), / (division), ^ (exponentiation), = (equality), == (identity), < (less than), > (greater than), <= (less than or equal), >= (greater than or equal), ~= (not equal), ~== (not identical), & (logical and), | (logical or), or := (assignment). When binary operator calls are chained together, they are grouped by rules of precedence and associativity and by parentheses — for example, (a - b) * x + c * x ^ 2. A binary operator call is actually an abbreviated notation for a function call or function-macro call. The rules of precedence are given in Table 4-1, Operators, on page 37.

An element reference consists of an operand that indicates a collection and an expression in square brackets that indicates a key. Instead of a key, there can be multiple expressions separated by commas that indicate array indices; for example, c[k] or a[i, j]. This is actually an abbreviated notation for a function call.

A slot reference is another abbreviated notation for a function call. It consists of an operand that indicates an object, a period, and a named value reference that indicates a one-argument function to apply to the object. Typically the function is a slot getter but this is not required, as in airplane.wingspan.

A parenthesized expression is any expression inside parentheses. The parentheses have no significance except to group the arguments of an operator or to turn a general expression into an operand; for example, (a + b) * c.