---
title: Functions
canonical_url: https://mew-lang.org/language/functions/
sidecar_url: https://mew-lang.org/language/functions.md
content_hash: sha256:009dcd0b1592f30891201289ce6f78b0af5804255bf31ab51ca3b034415bf1ae
tokens: 2450
uid: language.functions
reading_time_minutes: 8
---

Language
# Functions

 
A function declared outside a type is a free function.

 
```mew
use std;
  
pub fn squared(value: i32) -> i32 {
    return value * value;
}
  
println($"{squared(8)}");
```

 
A function is declared at the top level of a file. There are no functions inside other functions. A [lambda](https://mew-lang.org/language/lambdas.md) is what a function written inside another one looks like.

 
Declarations are found before any body is bound, so a function may call one written below it.

 
## Visibility

 
`pub` makes a function visible to other files. Without it the function belongs to the file that declares it, which is narrower than its [namespace](https://mew-lang.org/language/namespaces.md#visibility).

 
```mew
use std;
  
pub fn shared() -> i32 {
    return 1;
}
  
fn local() -> i32 {
    return 2;
}
  
println($"{shared() + local()}");
```

 
That applies to free functions. A function declared inside a `type` is a [method](https://mew-lang.org/language/types.md#methods), and its visibility is scoped to the type rather than to the file.

 
## Parameters and results

 
A parameter is written `name: type`, and parameters are separated by commas. A missing `->` means the function returns [void](https://mew-lang.org/language/primitives/void.md).

 
```mew
use std;
  
pub fn between(value: i32, low: i32, high: i32) -> bool {
    return value >= low && value <= high;
}
  
pub fn announce(text: string) {
    println(text);
}
  
announce($"{between(5, 1, 10)}");
```

 
A parameter is immutable unless it says `mut`, the same as a local. What `mut` allows is writing to the copy the call passed, which the caller never sees.

 
```mew
use std;
use std.convert;
  
pub fn shift(mut step: i32) -> i32 {
    step = step + 1;
    return step;
}
  
let held = 1;
  
println(itoa(shift(held)));
println(itoa(held));
```

 
`held` is still `1`. A parameter without `mut` reports MEW2116 when it is assigned.

 
A call passes its arguments in order. It can also name the parameter an argument fills, leave out a parameter that carries a default, or hand over more arguments than the declaration lists.

 
## Naming an argument

 
An argument may say which parameter it fills, so a bare number at a call site says what it is for.

 
```mew
use std;
  
pub fn area(width: i32, height: i32) -> i32 {
    return width * height;
}
  
println($"{area(640, 480)}");
println($"{area(640, height: 480)}");
println($"{area(height: 480, width: 640)}");
```

 
Every argument without a name fills the parameter at its own position, so those come first. A bare argument written after a named one is an error, because there would be no position left to give it.

 
```mew
pub fn area(width: i32, height: i32) -> i32 {
    return width * height;
}
  
let size = area(height: 480, 640);
```

 
Naming a parameter the function does not have is an error too, as is giving one a value twice.

 
```mew
pub fn area(width: i32, height: i32) -> i32 {
    return width * height;
}
  
let size = area(640, depth: 480);
```

 
Names let arguments be written out of order, and reordering them changes nothing about what runs first. Arguments are evaluated in the order the parameters are declared, whatever order the call writes them in.

 
## Default values

 
A parameter may carry a value to use when a call leaves it out.

 
```mew
use std;
  
pub fn connect(host: string, port: i32 = 8080, tls: bool = true) -> string {
    return $"{host}:{port} {tls}";
}
  
println(connect("localhost"));
println(connect("localhost", 9000));
println(connect("localhost", tls: false));
```

 
Without a name there would be no way to skip `port` and still say something about `tls`.

 
A default has to be a literal. A declaration is read before any name in the file is bound, so there is nothing yet for an expression to reach.

 
```mew
pub fn connect(port: i32 = 40 * 2) -> i32 {
    return port;
}
```

 
Everything after a parameter with a default needs one too, since otherwise no call could reach it.

 
```mew
pub fn connect(port: i32 = 8080, host: string) -> i32 {
    return port;
}
```

 
Where a type implements an [interface](https://mew-lang.org/language/interfaces.md), the interface declares the default and the implementation may not restate it. Two defaults for one parameter would be picked by the type a call was written against rather than by the value it was made on, so the same object would answer two ways.

 
## Gathering what is left

 
The last parameter may gather whatever arguments the call has left, written with `...` before its type. Inside the function it is an [array](https://mew-lang.org/language/arrays.md) of that type.

 
```mew
use std;
  
pub fn sum(values: ...i32) -> i32 {
    let mut total = 0;
    for value in values {
        total = total + value;
    }
  
    return total;
}
  
println($"{sum()}");
println($"{sum(1, 2, 3)}");
```

 
A call that writes nothing for it gathers an empty array, so a gathering parameter never needs a default and cannot carry one. Nothing may follow it either, because there would be no argument left to reach.

 
A single trailing argument that already has the array type is handed over as it stands rather than gathered into another array. There is no spread operator, so without that rule nothing could forward what it was given.

 
```mew
use std;
  
pub fn count(values: ...i32) -> i32 {
    return values.count;
}
  
let numbers = new i32[] { 1, 2, 3, 4 };
  
println($"{count(1, 2)}");
println($"{count(numbers)}");
```

 
Nothing gathers by name, so an argument cannot name a gathering parameter. Whether a trailing array is handed over or gathered is decided by the parameter's element type, so one whose element type is still a [type parameter](https://mew-lang.org/language/generics.md) always gathers.

 
## Every path has to return

 
A function that declares a return type has to produce one on every path through it. A path that falls off the end is an error, reported after the program is bound from a control flow graph built for the function.

 
```mew
pub fn sign(value: i32) -> i32 {
    if value > 0 {
        return 1;
    }
}
```

 
Give the last path an answer.

 
```mew
use std;
  
pub fn sign(value: i32) -> i32 {
    if value > 0 {
        return 1;
    }
  
    return -1;
}
  
println($"{sign(3)}");
```

 
A `void` function needs no `return` at all, and a `loop` with no `break` never falls out of its block, so a function whose body is one owes nothing after it.

 
A path that ends in a call to a function marked [[noreturn]](https://mew-lang.org/language/attributes.md#noreturn) also owes no `return`, because nothing after such a call runs. That is what lets [panic](https://mew-lang.org/stdlib.md#stopping-early) stand in for one.

 
```mew
use std;
  
pub fn pick(flag: bool) -> i32 {
    if flag {
        return 1;
    }
  
    panic("no value");
}
  
println($"{pick(true)}");
```

 
A statement no path can reach is a warning rather than an error, so the compiler points at code that will never run without refusing to build.

 
```mew
use std;
  
pub fn first() -> i32 {
    return 1;
    println("never");
    return 2;
}
  
println($"{first()}");
```

 
## Overloading

 
Several functions may share a name as long as their parameters differ, in type or in number. The one whose parameters fit the arguments is the one called.

 
```mew
use std;
  
pub fn describe(value: i32) -> string {
    return $"{value}";
}
  
pub fn describe(value: string) -> string {
    return value;
}
  
println(describe(32));
println(describe("Ada"));
```

 
The return type is not part of what tells two functions apart, so declaring the same parameters twice is an error however the results differ.

 
```mew
pub fn read() -> i32 {
    return 1;
}
  
pub fn read() -> string {
    return "one";
}
```

 
A call that leaves out an optional parameter still has to pick, and the candidate the call writes every argument for wins over one that would fill a parameter from its default. A candidate that gathers loses to every candidate that does not, however well its own parameters fit. That is what lets a gathering function hand what it gathered to an overload taking a sequence, instead of resolving back to itself.

 
```mew
use std;
  
pub fn total(values: ...i32) -> i32 {
    return total(values);
}
  
pub fn total(values: Enumerable<i32>) -> i32 {
    let mut sum = 0;
    for value in values {
        sum = sum + value;
    }
  
    return sum;
}
  
println($"{total(1, 2, 3)}");
```

 
Overloading covers methods and members added by an [impl block](https://mew-lang.org/language/extending.md) the same way. Where an argument is a [union case written without its union](https://mew-lang.org/language/unions.md#leaving-the-union-out), the case name is what picks between candidates.

 
## Functions as values

 
A function's name, written without a call, is a value of its function type, which is what lets one function be handed to another.

 
```mew
use std;
  
pub fn twice(n: i32) -> i32 {
    return n * 2;
}
  
pub fn apply(f: fn(i32) -> i32, value: i32) -> i32 {
    return f(value);
}
  
println($"{apply(twice, 21)}");
```

 
A name that means more than one function has no single type, so it cannot be held on its own, because nothing at that point says which one was meant.

 
[Lambdas](https://mew-lang.org/language/lambdas.md) cover function types, writing a function inline, and what a lambda captures.

 
## What functions do not have

 
There is no partial application and no way to compose two functions into a third. A lambda that closes over what it needs covers the same ground.

 
[Previous
                
                Operators](https://mew-lang.org/language/operators.md)[Next
                    
                Lambdas](https://mew-lang.org/language/lambdas.md)