Skip to content

Functions

Functions are first-class values in Nic. They can be passed as arguments, returned from other functions, and stored in variables.

Basic Functions

nic
fn add(a: i32, b: i32) -> i32 {
    return a + b;
}

fn greet(name: string) -> unit {
    println("Hello, " + name + "!");
    return;
}

fn main() -> unit {
    let sum: i32 = add(3, 4);
    greet("World");
    return;
}

Parameters and Return Types

Every parameter must have an explicit type. The return type follows ->:

nic
fn multiply(x: i32, y: i32) -> i32 {
    return x * y;
}

fn divide(x: f64, y: f64) -> f64 {
    return x / y;
}

// No return value uses 'unit'
fn log_message(msg: string) -> unit {
    println(msg);
    return;
}

Function Types

Functions have types and can be stored in variables:

nic
fn double(x: i32) -> i32 {
    return x * 2;
}

fn main() -> unit {
    // Function type: fn(i32) -> i32
    let f: fn(i32) -> i32 = double;
    
    let result: i32 = f(21);  // 42
    return;
}

Higher-Order Functions

Functions that take or return other functions:

nic
fn apply(f: fn(i32) -> i32, x: i32) -> i32 {
    return f(x);
}

fn square(n: i32) -> i32 {
    return n * n;
}

fn main() -> unit {
    let result: i32 = apply(square, 5);  // 25
    return;
}

Lambda Expressions

Anonymous functions (closures) are written with fn:

nic
fn main() -> unit {
    // Lambda expression
    let double = fn(x: i32) -> i32 { return x * 2; };
    
    let result: i32 = double(21);  // 42
    
    // Inline lambda
    let squared: i32 = apply(fn(n: i32) -> i32 { return n * n; }, 4);
    
    return;
}

fn apply(f: fn(i32) -> i32, x: i32) -> i32 {
    return f(x);
}

Closures Capture Variables

Lambdas can capture variables from their enclosing scope:

nic
fn make_adder(n: i32) -> fn(i32) -> i32 {
    return fn(x: i32) -> i32 { return x + n; };
}

fn main() -> unit {
    let add_10 = make_adder(10);
    let result: i32 = add_10(5);  // 15
    
    return;
}

Visibility

Functions are private by default. Use pub to make them public:

nic
pub fn public_function() -> unit {
    return;
}

fn private_function() -> unit {
    return;
}

External Functions (C FFI)

Declare C functions to call from Nic:

nic
extern fn printf(format: string, ...) -> i32;
extern fn malloc(size: size_t) -> opaque;
extern fn free(ptr: opaque) -> unit;

fn main() -> unit {
    printf("Hello from C!\n");
    return;
}

Exporting to C

Export Nic functions callable from C:

nic
pub extern fn add(a: i32, b: i32) -> i32 {
    return a + b;
}
// C can call: int32_t add(int32_t a, int32_t b);

Summary

FeatureSyntax
Basic functionfn name(params) -> Type { body }
Function typefn(T1, T2) -> R
Lambdafn(params) -> Type { body }
Publicpub fn name(...) -> Type { }
Externalextern fn name(...) -> Type;
Exportpub extern fn name(...) -> Type { }

Next

Learn about Control Flow to make decisions in your code.

Released under the MIT License.