On this page:
def
block
fun
fun
#%call
->
let
letrec
:  =

4 Definitions and Functions🔗ℹ

When defining or locally binding a name, some predefined names must be avoided. The following names are disallowed for binding, since redefining or shadowing the names could easily create confusion: def, fun, block, let, letrec, if, cond, match, check, try, module, import, type, is_a, Int, Boolean, Void, String, Symbol, Listof, Arrayof, Mapof, Syntax, Boxof, cons, first, rest, values, box, unbox, set_box, Array, and MutableMap.

definition

def typed_id = expr

 

definition

def typed_id:

  body

 

definition

def values(typed_id, ...) = expr

 

definition

def values(typed_id, ...):

  body

 

definition

def mutable typed_id = expr

 

definition

def mutable typed_id:

  body

A definition of one typed_id to the result of expr or body, or to multiple typed_ids to the components of the tuple result of expr. When mutable is specified, then the defined identifier’s value can be changed using :=.

def x = 1

def x2 :: Int = 2

> x

- Int

1

> x2

- Int

2

def s :: String = 0

typecheck failed: String vs. Int

def values(x3 :: Int, s2 :: String):

  values(3, "apple")

def mutable count = 0

> count

- Int

0

> count := count + 1

- Void

> count

- Int

1

expression

block:

  body

Expression form that allows nested definitions and side-effect expressions before a final expression. The body within block is a sequence of definitions and expressions ending in an expression. The last expression in the body sequence provides the type and result value of the sequence.

Any expression in the sequence before the last one must have type Void, and such an expression is useful only when it has a side effect (such as printing), since the result is ignored.

Names defined by definitions in body are visible only within the block body, and they shadow bindings of the same name outside of the block.

Forms like fun and match have body positions, and you can think of those positions as implicitly having a block around the body.

> def x = "outside"

> x

- String

"outside"

> block:

    def x = "inside"

    println("hello")

    x

- String

hello

"inside"

> x

- String

"outside"

definition

fun id (typed_id, ...) maybe_type:

  body

 

expression

fun (typed_id, ...) maybe_type:

  body

 

maybe_type

 = 

ϵ

 | 

:: type

The fun form is a definition when id appears immediately after fun, otherwise it’s an expression form. Each of the typed_id arguments optionally declares a type for the argument, and if maybe_type is not empty, it declares the function’s result type.

A function is called through the expression form fun_expr(arg_expr, ...), where fun_expr is typically an identifier defined with fun, but it can be any expression that produces a function. A function call of the form fun_expr(arg_expr, ...) is an implicit use of #%call.

fun fib(n :: Int) :: Int:

  cond

  | n == 0: 1

  | n == 1: 1

  | ~else: fib(n-1)+fib(n-2)

> fib(10)

- Int

89

fun on_three(f :: Int -> Int) :: Listof(Int):

  [f(1), f(2), f(3)]

> on_three(fun (x): x*10)

- Listof(Int)

[10, 20, 30]

expression

fun_expr #%call (arg_expr, ...)

A function call. Typically, #%call is not written, but an expression of the form fun_expr(arg_expr, ...) is an implicit use of #%call.

fun addone(x): x+1

> addone #%call (0)

- Int

1

The type of a function. The arg_types specify the types of arguments, while result_type is the type of the result.

The -> operator associates to the right, so a -> b -> c is the type of a function that takes a and returns a function of type b -> c.

> fun (x): x + 1

- Int -> Int

#<function:fun>

fun make_adder(n :: Int) :: Int -> Int:

  fun (x): x + n

> make_adder

- Int -> Int -> Int

#<function:make_adder>

fun apply_adder(adder :: Int -> Int) :: Int:

  adder(10)

> apply_adder

- (Int -> Int) -> Int

#<function:apply_adder>

expression

let id = rhs_expr:

  body

 

expression

letrec id = rhs_expr:

  body

Shorthands for a block containing a definition of id to rhs_expr followed by expr, except that in the case of let, id is not visible to the rhs_expr.

See macro for the definition of let in terms of block and def.

> let x = 1:

    let x = x + 2:

      x

- Int

3

> letrec sum = (fun(lst):

                  match lst

                  | []: 0

                  | cons(n, lst): n + sum(lst)):

    sum([1, 2, 3])

- Int

6

expression

id := expr

Changes the value of id to the result of expr. The id must have been defined using def mutable. The type of id and the type of expr must be the same.

No useful result is produced by the assignment expression. That is, the type of the := expression is Void.

> def mutable x = 1

> x := 2

> x

2