Skip to content

Functions

Function declaration grammar is given in Declarations.

A function whose first parameter is an E#-declared data (value or *T) is promoted to a method on that type. Promotion is by-attachment across files; it does not apply to choice, enum, primitives, or external/C# types.

The call shape depends on the receiver kind:

ReceiverFree call f(x)Method call x.f()In method set of
value func f(x: T)ill-formed — ES2142requiredT and *T
pointer func f(x: *T)validvalid*T only

A value-receiver method has no static host: it is reachable wherever its receiver type is in scope, regardless of declaring namespace. A pointer-receiver function remains a namespace-scoped free function that also joins *T’s method set. A function with a readonly *T first parameter is not promoted (a value-type this is always mutable).

ReturnType = ( "->" | "returns" ) Type .
ReturnsClause = "returns" Type . // class-level, inside ref data / static func

returns T is a synonym for -> T in a signature. As a standalone clause inside a ref data or static func body it sets the default return type for member functions that omit their own annotation; an explicit -> T on a member overrides it.

A promoted call chains when a method returns a value the next call lands on. A method returning its receiver yields a fluent API; for a ref data this returns the same instance (mutation threads through), for a value data a fresh value each step. A chain may break across lines with a leading dot — a newline before . continues the chain. A method returning Result<T, E> does not chain; unwrap each step with ?.

Lambda = "func" "(" [ ParamList ] ")" [ ReturnType ] ( Block | "=" Expr )
| "(" [ identifier { "," identifier } ] ")" "=>" Expr .

A function literal closes over the enclosing scope. Captures are mutable — a write inside the closure is visible outside and vice versa; a closure over a let binding may read but not assign it (compiler- enforced). Arrow-lambda parameter types are inferred when a delegate type is expected at the call site. Captured variables are hoisted into a generated display class shared by the outer scope and all closures over those captures.

FuncPtrType = "&" "(" [ TypeList "->" ] Type ")" . // &(int, int -> int) , &(string -> void) , &(-> bool)

&f takes a function’s address — zero allocation, single-target, emitted as ldftn + calli. A function-pointer type is first-class (struct fields, parameters, locals). The binder verifies signature compatibility at the call site. Function pointers are the systems tier; heap-allocated, multicast delegates are the interop tier — see Delegates & events. The disambiguation between &f (function pointer) and &x (address-of a variable) is by what the name resolves to; see Pointers & by-ref.