Previous chapter: Language Overview

Dylan manual: Syntax and Semantics

3. Syntax and Semantics

Lexical Notation[next citation]

Dylan programs are written using a parenthesized Lisp notation FN4.

White Space (including spaces, tabs, newlines, and newpage characters) serves as a delimiter. The amount of contiguous white space is not significant. Thus, any number of contiguous white space characters can be used for formatting.
(...)
Lists are delimited by open and close parentheses. The items between the parentheses are the elements of the list.

'#(...)'
Vectors (one-dimensional arrays) are represented using list notation, preceded by a hash-sign.
foo
Symbols are a series of alphanumeric and symbolic characters that do not indicate a number. Symbols are not case-sensitive, though they do retain case information. FN5
foo:
Keywords are used as symbolic constants. They look like symbols ending in colons. However, they are not symbols. They are a distinct class of objects.
123
1.5
-4.0
+57
#x1f4e
The syntax of numbers is described in the numerics section of this manual.
"abc"
Strings are delimited by double-quote marks. The characters between the quotes are the elements of the string. Within the string, white space is significant (it contributes to the string). Double quotes can be included in strings by preceding them with a backslash character. Within a string, backslash (\) has the general effect of quoting the following character. To include a backslash in a string, the backslash must be preceded by another backslash.
'#'a
#\space
Characters are represented by a hash-sign, followed by a backslash, followed by the character or the name of the character. Character names include newline, space, rubout, page, tab, backspace, return, and linefeed.
;
A semicolon indicates the start of a comment. The comment continues until the end of the line. At the start of a new line, regular parsing begins again.
'#|...|#'
Hash-sign/vertical-bar pairs delimit extended comments. These comments can run over multiple lines. Extended comments can be nested.
{...}
Curly braces are used to delimit unreadable objects. These are objects (for example, generic functions) that do not print out in a format that can be reliably read back into Dylan.
'
A single quote mark is used to introduce literal constants. It is an abbreviation for the quote special form.
`
A backquote is used to introduce a section of partial quotation. Backquote is described in a separate section of this manual.
'#t[next citation]'
The hash-sign t syntax is used to indicate the canonical true value.
'#f[next citation]'
The hash-sign f syntax is used to indicate the canonical false value.
'#key[next citation]'
'#rest[next citation]'
'#next[next citation]'
#key, #rest, and #next are used to indicate special tokens in parameter lists.

Conventions[return to first citation]

Programs written in Dylan, and Dylan itself, use the following conventions.

Variable Names

Several conventions for naming variables help programmers identify the purposes of variables. With the exception of setter variables (described below), the names of variables do not affect the semantics of a program, but are simply used to improve readability.

Variables used to hold classes begin and end with angle brackets.

<window>
<object>
<character>
<number>
<stream>
<list>
Module variables that are designed to have their values change in the course of a program (i.e., variables that are not read-only) begin and end with asterisks.

*parse-level*
*incremental-search-string*
*machine-state*
*window-count*

Program constants[next citation] (read-only module variables) begin with a dollar sign.

$pi
$end-of-file
The names of predicate functions end with a question mark. Predicates are functions which return a true or false value. FN6

subclass?
even?
instance?
id?
The names of operations that destructively modify data structures end with an exclamation point. These names sometimes contrast with versions that allocate new memory for the result.

set!
reverse!
(non-destructive version is reverse)
sort!
(non-destructive version is sort)
See Also Dylan Design Notes: New Syntax for Setter Variables (Change)

Operations that retrieve a value from a location are called getters. Operations that store into a location are called setter[return to first citation]s. In general, getters and setters come in pairs. The getter will be stored in a symbol variable, and the setter will be stored in the corresponding setter variable. This is actually not simply a convention. The rule is exploited to generate setter names from getter names automatically, and it is used to expand calls to set!.

Getter             Setter 
window-position   (setter window-position)
table-size        (setter table-size)
window-color      (setter window-color)
These two expressions are roughly equivalent; they both set the color of my-window to green:

((setter window-color) my-window green)
(set! (window-color my-window) green)
See Also: Dylan Design Notes: Definitions are Declarative (Change)

Expressions and Programs

Dylan programs are composed of expressions. When an expression is evaluated, it returns zero or more values. Evaluating an expression may have side effects and may involve evaluating sub-expressions.

There are four kinds of expressions: literal constants[return to first citation], variable references, function calls, and syntax forms. FN7

Literal Constants

Literal constantssuch as numbers, strings, and keywordsmay be directly embedded in programs. Literal constants evaluate to themselves. In addition to numbers and strings, some system constants are provided, for example, #t and #f (Boolean true and false).

Symbols and lists (which have special evaluation rules) must be quoted to be used as literal constants. Quoting is performed with the syntax form quote, which is usually abbreviated to a single quote mark ( ' ).

  ? "abc"
   "abc"
   ? 123
   123
   ? foo:
   foo:
   ? #\a
   #\a
   ? #t
   #t
   ? #f
   #f
   ? (quote foo)
   foo
   ? 'foo
   foo
   ? '(1 2 3)
   (1 2 3)
Variable References

When an expression is a variable name, the expression indicates a variable reference. The variable name evaluates to the value of the variable.

There are two syntaxes for variable names in Dylan. A variable name can be a symbol, or it can be a two-element list whose first element is the symbol setter and whose second element is another symbol. The latter syntax is used to create setter variables. Setter variables can be used in all the same situations as symbol variables.

The symbol setter cannot be used as a variable name. This restriction is necessary to prevent ambiguities in the syntax. The following are examples of legal variable names:

position
my-variable
(setter position)
(setter another-variable)
Dylan supports two kinds of variables: lexical variables and module variables. Lexical variables are created locally and can be referenced only in a limited range of program text. Method parameters are an example of lexical variables; they can be referenced from the body of the method but not from anywhere else.

Module variables are created by using a define form. Module variables can be referenced by any expressions defined in the same module. Module variables play the role assumed by global variables, unit variables, and pool variables in other languages.

  ? <window>
   {the class <window>}
   ? concatenate
   {the generic function concatenate}
   ? (define my-variable 25)
   my-variable
   ? my-variable
   25
   ? (bind ((x 50))
     (+ x x))
   100
   ? (setter element)
   {the generic function (setter element)}
   ? (define (setter my-variable) 20) FN8 
   (setter my-variable)
   ? (setter my-variable)
   20
Function Calls

A list whose first element is not a syntax operator or setter is a function call. The function to be called is the value of the first element in the list. The arguments to the function are the values of the remaining elements in the list.

The arguments to a function are evaluated in left-to-right order. The function may be evaluated at any time before, during, or after the arguments are evaluated. Once the function and all the arguments are evaluated, the function is called with the arguments.

Note that the same rules are used to evaluate the function and argument parts of an expression. The expression in the function position does not have to be a variable reference; it can be any expression that evaluates to a function. In this way, Dylan is like Scheme and unlike Common Lisp.

A function call evaluates to the values returned by the function.

  ? (+ 3 4)
   7
   ? (* my-variable 3)
   75
   ? (* (+ 3 4) 5)
   35
   ? ((if #t + *) 4 5)
   9
See Also: Dylan Design Notes: Definitions are Declarative (Change)

Syntax Forms

A list whose first element is a special form operator or macro operator is a syntax form. Every syntax form has its own rule for evaluation.

Special form operators and macro operators are together called syntax operators.

Syntax forms look like function calls (that is, they are represented as lists). However, syntax forms are not function calls. In a function call, all the subexpressions are evaluated and passed to the function as arguments. In contrast, a syntax form can examine its subexpressions literally and can choose to evaluate some and give special meaning to others. For example, the special form bind parses its first subexpression into a variable binding list.

Some examples of syntax operators are define, set!, bind, and method.


   ; Creates and initializes a module variable
   (define my-variable 25)
   ; Sets the value to 12
   (set! my-variable 12)
   ; Returns 30. Uses lexical variables x and y.
   (bind ((x 10) (y 20))
      (+ x y))
   ; Creates an anonymous method, which expects 2 
   ; numeric arguments.
   (method ((a <number>) (b <number>))
      (list (- a b) (+ a b)))

Multiple Values Evaluating a Dylan expression can yield one value, more than one value, or no values at all. This capability is called multiple values.

Multiple values are supported through two capabilities: the function values is used to return multiple values; and bind (described in the section on Lexical Variables, below) is used to receive multiple values.

values[return to first citation]   #rest the-values   X  the-values	[Function]
Returns the-values as multiple values.

 ? (values 1 2 3)
 1
   2
   3
   ? (define-method edges ((center <number>)(radius <number>))
       (values (- center radius) (+ center radius)))
   edges
   ? (edges 100 2)
   98
   102

Next chapter: Variables