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:
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.