We don’t support first-class functions very well. Really, we only support lambdas. We’d like to support first-class functions, and need to change the language to do it
5 |> Ok
)let x = Int.add
)x 5 6
)List.map [...] increment
)let x y z = …
)let x = Result.Ok; x 5
)let add5 = Int.add 5
)let main () =
let doThing = \\var -> ... // lambda
List.iter listing doThing
When parsed to ProgramTypes.Expr:
ELet ("doThing", ELambda (["var"], ...),
EFnCall ("List.iter", [EVariable "listing"; EVariable "doThing])
doThing
is a variable containing the lambda value
This uses
type Expr = // ProgramTypes
...
| ELambda of id * List<id * string> * Expr
| EFnCall of id * FQFnName.T * typeArgs : List<TypeReference> * args : List<Expr>
When converted to RuntimeTypes.Expr:
ELet ("doThing", ELambda(["var"], ...),
EApply (FnName("List.iter), [EVariable "listing; EVariable "doThing"])
Which is defined as
type Expr = // RuntimeTypes
...
| EApply of id * FnTarget * typeArgs : List<TypeReference> * args : List<Expr>
| ELambda of id * List<id * string> * Expr
and FnTarget =
| FnName of FQFnName.T
| FnTargetExpr of Expr
When evaluating ELambda
in the interpreter, we get:
DFnVal(Lambda { symtable = st; parameters = parameters; body = body })
DFnVal
is:
and LambdaImpl = { parameters : List<id * string>; symtable : Symtable; body : Expr }
and FnValImpl = Lambda of LambdaImpl
and dval =
...
| DFnVal of FnValImpl