Back Contents Next

4. Expressions

4.1 Variable References

syntax: <symbol>

An expression consisting of a symbol is a variable reference. The value of the variable reference is the value stored in the location to which the variable is bound. It is a error to reference an unbound variable. The names of all entities described in this report are bound to the location of the functions described herein. Thus all function names, numbers and other literals are already bound.

4.2 Literal Expressions

syntax: <literal>

A literal is an identfier which stands for a particular entity. That entity is substituted for the literal. The identfiers which correspond to literals can be found in section 2.3 Literals.

syntax macro: '<expression>
macro: (quote <expression>)

'<expression> is an abbreviation for (' <expression>). This is an invocation of the quote macro which returns its argument unevaluated thus forming essentially a literal expression

4.3 Invocation

syntax: (<operator> <operand1> ...)
syntax: [<operator> <operand1> ...]

A function/continuation call or macro instantiaiton is written by simply enclosing in parentheses or square brackets expressions for the entity to be invoked and the arguments to be passed to it. First the operator expression is evaluated. If the operator is a function/continuation then the operand expressions are evaluated (in an unspecified order) and the resulting function/continuation is passed the resulting arguments.

(+ 3 4)=>7
((if #f + *) 3 4)=>12

A number of functions are available as the values of variables in the initial environment; for example, the addition and multiplication functions in the above examples are the values of the variables '+' and '*'. New functions are created by evaluating lambda macros (see section 5.1.1 Lambda).

Function calls may return any number of values (see values in section see section 6.4 Control features). With the exception of 'values' the functions available in the initial environment return one value or, for functions such as 'apply', pass on the values returned by a call to one of their arguments.

Note: In contrast to other dialects of Lisp, the order of argument evaluation is unspecified, and the operator expression and the operand expressions are always evaluated with the same evaluation rules.

Note: Although the order of evaluation is otherwise unspecified, the effect of any concurrent evaluation of the operand expressions is constrained to be consistent with some sequential order of evaluation. The order of evaluation may be chosen differently for each procedure call.

4.3.1 Function Calls

If the entity being invoked is a function then the invocation constitutes a function call. A function can have zero or more arguments. If the number of arguments being passed is equal to the number expected by the function then they are passed, the function is invoked and the expression evaluates to the return value of the function.

Better Scheme supports currying of function arguments. This comes into play if either more or fewer arguments are passed then expected. If fewer arguments are passed than expected, the result is a function expecting the remaining arguments that when invoked will return the result of calling the original function with the complete set of arguments. If more arguments are passed then expected then the function is invoked with the number of arguments it expected and the return value of the function is invoked with the remaining argument. Note that this process could occur repeatedly.

4.3.2 Unrestricted Function Calls

If the entity being invoked is an unrestricted function then the invocation constitutes a unrestricted function call. An unrestricted function accepts any number of arguments (including zero) and recieves them as a list of the arguments (regardless of whether the invocation expression was a list or vector).

Currying an unrestricted function requires special handling. If you wish to pass extra arguments it is not too much of an imposition to simply enclose the original call in a set of parenthesis and use another set to invoke the return valuel. However, if one wishes to pass fewer arguments than "expected" there is no obvious way to do that. For this case there is a special notation. Terminate the arguments list improperly with #void. For example:

(unrestricted-function arg1 arg2 arg3 .#void)

4.3.3 Continuation Calls

if the entity being invoked is a continuation (created by call/cc) then the invocation is a continuation invocation. Continuations accept a single argument and transfer control without returning. This changes the way currying works. If a continuation is invoked with no arguments then the continuation is returned. If a continuation is invoked with extra arguments then the extra arguments are ignored becuase there is no return value from a contiation and execuation has left the site of the invocation.

4.3.4 Macro Instantiation

If the entity being invoked is a macro then the invocation is a macro instatiation. A macro matches its arguments against a series of argument patterns. If none match it is an error. When a match is found then the macro body is instatiated at the call site. This can be thought of as the macro expanding to the text of its body at the call site. Since macros are hygenic they can introduce new names which will not conflict with names in scope at the call site. Macros can also break this and intentionally capture or create names at the call site. Macros by definition do not evaluate their arguments, rather they are instatiated then the resulting expression is evaluated.

4.4 Evaluative Operator

syntax: , <expression>

The evaluative operator causes the expression it proceds to be evaluated before being used. In contexts where the expression would have been evaluated anyway, the expression will first be evaluated then the result of that expression will be evaluated. In contexts (such as macro arguments) where the expression would not normally be evaluated this causes the expression to be evaluated before being used. This can leads to very unusal code. Consider:

(define a 1) (define b 2) (define var #void) (if foo (set! var 'a) (set! var 'b)) ,var (set! ,var '(1 2 3 ,(+ 2 2)))

Notice that the line ,var will access either a or b and display either 1 or 2 depending on the value of foo. Also, it will set the value of either a or b to (1 2 3 4). The line (set! ,var '(1 2 3 ,(+ 2 2))) is an example of how the evaluative operator is not simply a synonym of the eval function. Notice also that this demonstrates its use nested inside of a quote.



Back Contents Next

jwalker@cs.oberlin.edu