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

Goal

Supported right now

Lambdas

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