1.9 Anonymous Functions🔗ℹ

After we define a function, the name of the function can be used as a value without calling it. If you just evaluate the function name, then Shplait will print something like #<function>.

fun plus_five(n):

  n + 5

> plus_five

- Int -> Int

#<function:plus_five>

More usefully, you might pass the function to another function that calls it. For example, the map function takes a function and a list, and it applies the function to each element of the list to produce a new list.

> map(plus_five,

      [1, 2, 3])

- Listof(Int)

[6, 7, 8]

Sometimes, and especially with map, you need a one-off function that doesn’t need to be defined for everyone else to see, and it doesn’t even need a name. You can make an anonymous function by using fun without a name before the arguments:

> map(fun (n):

        n + 6,

      [1, 2, 3])

- Listof(Int)

[7, 8, 9]

The form fun (n): n + 6 means “the function that takes an argument n and returns n + 6.” You can evaluate a fun form without passing it anywhere, although that isn’t particularly useful:

> fun (n):

    n + 7

- Int -> Int

#<function:fun>

Notice that the result has a function type: it’s a function that takes a Int and returns a Int.

An anonymous function created with fun doesn’t have to stay anonymous. Since you can use a fun form anywhere that an expression is allowed, you can use in def:

def plus_eight = (fun (n):

                    n + 8)

This definition is completely equivalent to the function-definition shorthand:

fun plus_eight(n):

  n + 8

Another interesting property of anonymous functions is that, just like any local function, the body of a fun can see any surrounding variable binding. For example, the fun body in the following add_to_each function can see the m that is passed to add_to_each:

fun add_to_each(m, items):

  map(fun (n):

        n + m,

      items)

> add_to_each(7, [1, 2, 3])

- Listof(Int)

[8, 9, 10]

> add_to_each(70, [1, 2, 3])

- Listof(Int)

[71, 72, 73]

You can declare types for fun arguments and results similar to declaring them with the function-definition shorthand:

fun (s :: String) :: Boolean:

  string_length(s) > 10

- String -> Boolean

#<function:fun>