return statements — the last expression in a function body is its return value.
Basic syntax
Declare a function with thefn keyword:
-> arrow:
_ or a _-prefixed name for unused parameters:
Visibility
By default, functions are visible only within their package. Usepub to expose them to other packages, or pub(crate) to expose them within the same crate only:
The main function
In binary crates,main is the entry point. All its parameters must have a size known at compile time:
Call expressions
Call a function by name, passing arguments:Methods on structs
Define methods on any struct usingimpl blocks. The first parameter self refers to the receiver:
Specialization on generics
Implementations can be specialized for specific generic type arguments:Overlapping
impl blocks — for example, one for Foo<u32> and a blanket impl<T> Foo<T> — are not allowed. Noir must be able to unambiguously select which implementation to use.Lambdas
Lambdas are anonymous functions using the|args| expr syntax:
Closures
A lambda that captures variables from its enclosing scope is called a closure:fn[Env](args) -> ret. To accept both regular functions and closures, make the environment type generic:
Mutability
Variables are immutable by default. Declare mutable variables withmut:
&mut T) for non-local mutation:
Global variables
Globals are module-level constants with explicit types:pub or pub(crate) to control global visibility:
Attributes
Attributes apply metadata to functions using#[attribute] syntax. Common built-in attributes include:
#[test]
#[test]
Marks a function as a test case, runnable with
nargo test:#[foreign(name)]
#[foreign(name)]
Declares a function whose body is provided by the backend (a black-box function):
#[builtin(name)]
#[builtin(name)]
Declares a function that is built into the compiler:
comptime attribute functions
comptime attribute functions
Any
comptime function can be used as an attribute. The function receives the annotated item and can transform it:Unconstrained functions
Unconstrained functions execute outside the constraint system. They are useful for computation that is too expensive to prove directly — for example, performing division by using a hint that is later verified:loop/whileloopsbreakandcontinuein loops- Dynamic-length operations