Lambda

Lambdas are anonymous functions (functions without a name). "Without a name" just means they are declared without a name, you can still give them a name.

You can use lambdas for all sorts of things, usually they are used for quick, throw-away functions. This includes things such as arguments to #map and #each functions. Lambdas also play in important role in functional paradigm.

Lambdas in Cheddar have implicit return. The last statement's result will be implicitly returned. Always.

Note::Best Practice

In lambdas, what is being implicitly returned is easy to tell most of the time. However this is not the case for many statements such as loops and ifs.

Take for example this for loop:

input -> {
    for letter of input {
        if letter.ord() < letter.lower.ord() {
            letter.lower.ord()
        } else {
            letter.ord()
        }
    }
}

It's difficult to tell what this is returning but it is either letter.lower.ord() or letter.ord().

To avoid this, store the desired return value in a variable:

input -> {
    var result
    for letter of input {
        if letter.ord() < letter.lower.ord() {
            result = letter.lower.ord()
        } else {
            result = letter.ord()
        }
    }
    
    result // return value
}

If you want nothing to be returned, it is best to have the function return nil.

Syntax

Syntax for lambdas shoud be familiar to lambdas in other C-based languages. Cheddar's lambdas however have some more features:

Formal Syntax

The above roughly covers lambda usage. The formal syntax is along the lines of:

[ arguments ] "->" ( "{" code "}" | expression )

The syntax can be derived as:

Explanation

The lambda syntax is in the form: <arguments> [<self>] -> <code>.

<arguments> is the arguments to recieve from the lambda. This is either a single argument (described later), an array of arguments delimited by ( and ), or nothing.

<self> is an optional paramter. If you specify a variable name here. It'll be set to the function itself in it's body. This variable will be tail call optimized, so please use this for recursion.

<code> is either an expression, or a code block.

Argument Syntax

Lambda arguments are powerful and define what variables are passed to it, and how it is enforced.

An argument is a variable which is passed to the lambda from it's call. An argument can be any variable name. Which is described in the "Variables" chapter.

Type annotations on a variable enforce what type that variable must be. You can simply prepend: <type>: to the argument to add a type annotation. Without one, any type is accepted. Free whitespace is allowed around the :. An example is String: arg.

Optional arguments allow variables to not be passed. Usually if a value is not passed for a function's argument, an error is thrown. Appending a ? to the variable makes it optional. If a value is not supplied for the argument, it will be set to nil.

A default value is what a variable will be set to if no value is supplied. Default values cannot be used with optional arguments. To specify a default argument, append = <expression> where <expression> is an expression which evaluates to what the default value should be.

Argument Examples

Some examples of arguments:

arg                  Normal argument
arg?                 Optional argument
Bool: arg            Argument that must be a boolean
Bool: arg?           Optional argument that must be boolean if supplied
Bool: arg = false    Argument that must be a boolean that defaults to false

Lambda Examples

-> Number::IO.prompt('Number? ')

arg1 -> arg1 * 2

(arg1, arg2) -> arg1 + arg2

arg1 -> {
    var a = arg1 / 2
    [a * 3, a * 4]
}

n f -> n < 2 ? 1 : f(n - 1) + f(n - 2)

Last updated