next up previous contents
Next: FuncCall Up: Evaluation Rules Previous: Iterate   Contents


FuncDef

<

The function definition syntax allows a suffix of the formal parameters to have associated default values.

FuncDef    ::= Id Formals+ [ TypeQual ] Block
Formals    ::= ( FormalArgs )
FormalArgs ::= TypedId*,
             | { TypedId = Expr }*,
             | TypedId { , TypedId }* { , TypedId = Expr }+

The three alternatives for FormalArgs correspond to the cases in which no arguments are defaulted, all arguments are defaulted, and some arguments are defaulted, respectively.

Note that the syntax allows multiple Formals to follow the function name. As the rules below describe, the use of multiple Formals produces a sequence of curried functions, all but the first of which is anonymous.

<

Eval( Id Formals_1 ... Formals_n Block , C) =
  _bind1(id, Eval( e , C1)),

where:

Notice the recursive definition of C1. This allows functions to be self-recursive, but not mutually recursive. Although this recursive definition looks a little odd, it can be implemented by the evaluator by introducing a cycle into the context C1. This is the only case where any Vesta value can contain a cycle (the language syntax and operators do not allow cyclic lists or bindings to be constructed), and the cycle is invisible to clients. There is no practical difficulty in constructing the cycle because, as we are about to see, the ``evaluation'' of a LAMBDA is purely syntactic.

Also note that this rule produces a LAMBDA construct in the ``extended'' language that is not generated by any non-terminal of the grammar. The evaluation of LAMBDA produces a t_closure value $\langle e, f, b\rangle$ as described in Section A.3.1.

The following is the simple case of LAMBDA, where all actual parameters must be given in any application of the closure. The reason for the restriction on the use of ``.'' as a formal parameter is treated below in the section on function calls.

Eval( LAMBDA (Id_1, ..., Id_m)
      LAMBDA Formals_2 ... LAMBDA Formals_n Block , C) =
  <LAMBDA Formals_2 ... LAMBDA Formals_n Block, f, C>,

where f is a list of pairs $(\mbox{\em id}_i, \langle\mbox{emptyExpr}\rangle)$ such that $\mbox{\em id}_i$ is the t_text representation of Id_i, for $i$ in the closed interval $[1, m]$. If any of the identifiers Id_i is ``.'', the evaluation halts with a runtime error.

In the typical case where only one set of Formals is specified (that is, $n = 1$), the first element of the resulting closure value is simply a Block.

Next is the general case of LAMBDA, in which ``default expressions'' are given for a suffix of the formal parameter list. Functions may be called with fewer actuals than formals if each formal corresponding to an omitted actual includes an expression specifying the default value to be computed. When the closure is applied, if an actual parameter is missing, its formal's expression is evaluated (in the context of the LAMBDA) and passed instead. The following section on FuncCall defines this precisely.

Eval( 
    LAMBDA (Id_1,... Id_k, Id_k+1=Expr_k+1,... Id_m=Expr_m)
    LAMBDA Formals_2 ... LAMBDA Formals_n Block , C) =
  <LAMBDA Formals_2 ... LAMBDA Formals_n Block, f, C>,

where f is a list of pairs $(\mbox{\em id}_i, \mbox{\em expr}_i)$ such that:

As before, if any of the identifiers Id_i is ``.'', the evaluation halts with a runtime error.


next up previous contents
Next: FuncCall Up: Evaluation Rules Previous: Iterate   Contents
Allan Heydon, Roy Levin, Timothy Mann, Yuan Yu