| 58 | | defines a procedure named `f` which consumes inputs of types `T1`, ..., `Tn` and returns a value of type `R`. `R` can be `void` if the procedure does not return value. |
| 59 | | |
| 60 | | The definition above defines a *constant* `f` of type *`R(T1, ..., Tn)`*. Procedures are first-class values. One may declare a variable of type `R(T1, ..., Tn)`, a procedure may return a value of that type, a procedure may consume a value of that type, a value of that type may be assigned to a variable, etc. Hence the procedure type is just like any other type, and procedure definitions define new constants of that type, just as `1` is a constant of type `$int`. Note this is different from C in that C uses function pointers; PIL dispenses with the need for function pointers. |
| 61 | | |
| 62 | | A *procedure call expression* has the usual form `g(e1, ..., en)`. This is an expression that can be used anywhere an expression with side-effects is allowed. Here, `g` is an expression of functional type, say `R(T1, ..., Tn)`, and `ei` is an expression of type `Ti` (for i=1, ..., n). The procedure call expression has type `R`. |
| | 58 | defines a procedure named `f` which consumes inputs of types `T1`, ..., `Tn` and returns a value of type `R`. `R` can be `void` if the procedure does not return a value. |
| | 59 | |
| | 60 | The definition above defines a '''constant''' `f` of type '''`R(T1, ..., Tn)`'''. Procedures are first-class values. One may declare a variable of type `R(T1, ..., Tn)`, a procedure may return a value of that type, a procedure may consume a value of that type, a value of that type may be assigned to a variable, etc. Hence the procedure type is just like any other type, and procedure definitions define new constants of that type, just as `1` is a constant of type `$int`. Note this is different from C in that C uses function pointers; PIL dispenses with the need for function pointers. |
| | 61 | |
| | 62 | A '''procedure call expression''' has the usual form `g(e1, ..., en)`. This is an expression that can be used anywhere an expression with side-effects is allowed. Here, `g` is an expression of functional type, say `R(T1, ..., Tn)`, and `ei` is an expression of type `Ti` (for i=1, ..., n). The procedure call expression has type `R`. |
| 114 | | |
| 115 | | The type of this expression is `R(T1, ..., Tn)`. The resulting value of this is type is a procedure can be called or assigned to a variable, etc., just like any other procedure. |
| 116 | | |
| 117 | | Note that the definition can only use the specified variables. Evaluating this expression yields a closure, which is a pair consisting of a dyscope and the body of the procedure. The dyscope has variables `vj`, which are initialized by evaluating the `initj` when the lambda expression is evaluated. That dyscope will live as long as the procedure is around. Hence a function may return a closure and that closure may still be called at any time, anywhere in the program, regardless of whether the original lambda expression is in scope. |
| | 113 | * the only variables that can occur free in the block are the `xi` and `vj`. |
| | 114 | |
| | 115 | The type of this expression is `R(T1, ..., Tn)`. The resulting value of this is type is a procedure which can be called or assigned to a variable, etc., just like any other procedure value. |
| | 116 | |
| | 117 | Note that the definition can only use the specified variables. Evaluating this expression yields a closure, which is a pair consisting of a dyscope and the body of the procedure. The dyscope has variables `vj`, which are initialized by evaluating the `initj` when the lambda expression is evaluated. The body of the procedure may read and write to the `vj`. That dyscope will live as long as the procedure is around. Hence a function may return a closure and that closure may still be called at any time, anywhere in the program, regardless of whether the original lambda expression is in scope. |