Try Install Learn Blog API Packages GitHub
Pages

Functions

Functions are callable pieces of code which:

  • can take 0 or more parameters
  • can have 1 or more statements / expressions
  • can be defined in components, modules, stores, and providers

A function is defined by the fun keyword followed by its name, arguments and return type:

module Greeter {
  fun greet (name : String) : Html {
    <div>
      <{ "Hello " + name + "!" }>
    </div>
  }
}

Things to keep in mind:

  • the name of the function must:
    • start with a lowercase letter
    • contain only letters and numbers
  • type annotations for the arguments are mandatory
  • the return type annotation is optional, if not provided the return type will be inferred from the body of the function
  • the parentheses for the arguments can be left off if the function does not take any arguments.

Calling a function

You call a function with its name, providing zero or more arguments separated by commas in parentheses.

module Greeter {
  fun greet (name : String) : Html {
    <div>
      <{ "Hello " + name + "!" }>
    </div>
  }

  fun main : Html {
    greet("Bob")
  }
}

If the function belongs to a store or a module you can call it like this:

module Greeter {
  fun greet (name : String) : Html {
    <div>
      <{ "Hello " + name + "!" }>
    </div>
  }
}

component Main {
  fun render : Html {
    Greeter.greet("Bob")
  }
}

Functions as arguments

You can define a function which takes a function as an argument. The type of this argument must be defined and must match the type of the actual function passed at runtime. The function can be an anonymous or named function.

module Greeter {
  fun greet (name : String) : Html {
    <div>
      <{ "Hello " + name + "!" }>
    </div>
  }
}

component Main {
  fun renderGreeting (name : String, greeter : Function(String, Html)) : Html {
    greeter(name)
  }

  fun render : Html {
    renderGreeting("Bob", Greeter.greet)
  }
}

Here we passed the Greeter.greet function as an argument.

Type of a function

Functions have a specific type signature, like everything else in Mint. The type for the function includes the types of its arguments (in parentheses) and the return value last in list.

For a function like:

fun greet (name : String) : Html {
  <div>
    <{ "Hello " + name + "!" }>
  </div>
}

the type is:

Function(String, Html)

This can be read as:

A function which takes a String and returns Html

Anonymous functions

Anonymous functions look like this:

(suffix : String, match : Regex.Match) : String { match.match + suffix }
(event : Number) : Void { handleClick(event) }
() : Void { 42 }

The anonymous function starts with one or more argument definitions enclosed by parentheses followed by the type definition after a colon : , then a single expression that determines the return value enclosed by brackets.

This can be used as an expression anywhere you would use a value:

component Greeter {
  fun render : Html {
    <div onClick={(event : Html.Event) : String { Debug.log("Hello") }}>
      "Click Me!"
    </div>
  }
}

Recursive Functions

All functions can be called recursively:

component Main {
  fun fibonacci(num : Number) : Number {
    if num <= 1 {
      1
    } else {
      fibonacci(num - 1) + fibonacci(num - 2)
    }
  }

  fun render : Html {
    <div>
      <{ fibonacci(10) }>
    </div>
  }
}

Be careful when using recursive functions, the type-checker does not check if there is an exit condition, if there is not it will cause an infinite loop.

Pipe operator

The pipe operator |> can be used to pipe an expression into a function as the first parameter:

" Joe   "
|> String.toUppercase
|> String.trim
|> String.indent(2)

/* Is the same as */
String.indent(String.trim(String.toUppercase(" Joe   ")), 2)

Using this operator makes the code more readable.