Functions & Closures

Named functions and inline functions as first-class values

Notch has named function declarations and closures - anonymous function values you can pass around and call.

Quick reference

function add(a, b)
  return a + b
end

\-> 1                # zero-arg closure
\ s -> s.length      # one arg
\ x, y -> x == y     # multiple args

Named functions

Declare a function with function, a parameter list, and a block ended by end. Use return to produce a value:

function add(a, b)
  return a + b
end

Closures

A closure is an anonymous function value. The syntax is a backslash, an optional parameter list, an arrow, and an expression body.

Zero arguments:

\-> 1

One argument:

\ s -> s.length

Multiple arguments:

\ x, y -> x == y

Block-body closures

The arrow can also be followed by a brace-delimited statement block instead of a single expression:

\ x -> {
  y = x + 1
  print(y)
  return y
}

The block runs its statements top to bottom. Use return to produce a value; without one the block runs purely for side effects and the closure yields <undefined>. A bare trailing expression is not a statement - use return, or an expression body like \ x -> x + 1.

Closures as arguments

Closures can be passed to methods that expect functions:

['a', 'ab', 'abc'].map(\ s -> s.length)

Returns [1, 2, 3].

Closures in maps

Map values can be closures:

x = {'foo' -> \-> "bar"}
print(x.foo())
print(x[:foo]())

Both print bar.

Interop with java.util.function

Notch closures convert to JVM functional interfaces:

(\ x, y -> x == y).toBiFunction()
(\ x, y -> x == y).toBiPredicate()

The returned objects implement BiFunction and BiPredicate respectively.

See also