Changes between Version 7 and Version 8 of PIL


Ignore:
Timestamp:
10/04/24 13:28:06 (20 months ago)
Author:
siegel
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • PIL

    v7 v8  
    5656  R f(T1 x1, ..., Tn xn) { stmts }
    5757}}}
    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`. 
     58defines 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
     60The 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
     62A '''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`. 
    6363
    6464Procedure calls can have side-effects, be nondeterministic, and the behavior can depend on non-local state; they may access any variable in scope, the statements may dereference pointers, etc.
     
    9999=== Lambda expressions
    100100
    101 Lambda expressions can be used to define functions that are anonymous and that are *closures*, i.e., have an associated environment that persists for the life of the function.
    102 
    103 A lambda expression that specifies a procedure has the form:
     101Lambda expressions can be used to define functions that are anonymous and that are '''closures''', i.e., have an associated environment that persists for the life of the function.
     102
     103A lambda expression that specifies a procedure closure has the form:
    104104{{{
    105105  $lambda [U1 v1=init1; ... Um vm=initm;] R (T1 x1, ..., Tn xn) { S1; ... }
     
    110110* R is a type (the return type), which may be void
    111111* {S1; ...} is a block (same as in a procedure definition)
    112 * the only variables that can occur free in the block are the xi and vj
    113112* if R is not void, the block must return a value of 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
     115The 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
     117Note 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.
    118118
    119119A lambda expression that specifies a logic function has the form
     
    126126* R is a type (the return type), which cannot be void
    127127* `expr` is a side-effect-free expression of type R
    128 * the only variables that can occur free in `expr` are the xi and vj
     128* the only variables that can occur free in `expr` are the `xi` and `vj`.
    129129
    130130The type of this expression is `$fun<R, T1, ..., Tn>`.   As with procedural lambdas, this yields a logic function with a dynamic scope that persists, so can be called anywhere, even after the lambda expression goes out of scope.