Table of Contents

Functions

What is a function?

A function is a reusable block of instructions with a name. Think of it like a recipe: you define the steps once, and then you can use the recipe whenever you need it without writing the steps again.

You have already been using functions: main() is a function, and print() is a function built into Nyx.

Defining a function

fn greet() {
    print("Hello!")
    print("Welcome to Nyx.")
}

fn main() {
    greet()    // call the function
    greet()    // call it again
}

Output:

Hello!
Welcome to Nyx.
Hello!
Welcome to Nyx.

The function is defined once but called twice. Each call executes all the instructions inside the function.

Parameters — giving data to a function

Functions can receive inputs, called parameters:

fn greet(name: String) {
    print("Hello, " + name + "!")
}

fn main() {
    greet("Alice")     // Hello, Alice!
    greet("Bob")       // Hello, Bob!
    greet("Charlie")   // Hello, Charlie!
}

Multiple parameters are separated by commas:

fn add(a: int, b: int) {
    print(a + b)
}

fn main() {
    add(3, 5)      // 8
    add(10, 20)    // 30
}

Return values — getting data back from a function

Functions can send a result back using return:

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

fn main() {
    let result: int = square(5)
    print(result)    // 25
    print(square(8)) // 64
}

The -> int after the parameters declares what type the function returns. The return keyword sends the value back to whoever called the function.

Functions that return different types

fn is_adult(age: int) -> bool {
    return age >= 18
}

fn full_name(first: String, last: String) -> String {
    return first + " " + last
}

fn main() {
    print(is_adult(25))                    // true
    print(is_adult(12))                    // false
    print(full_name("Alice", "Smith"))     // Alice Smith
}

Recursion — a function calling itself

A function can call itself. This is called recursion:

fn factorial(n: int) -> int {
    if n <= 1 {
        return 1
    }
    return n * factorial(n - 1)
}

fn main() {
    print(factorial(5))     // 120 (5 × 4 × 3 × 2 × 1)
    print(factorial(10))    // 3628800
}

How it works:

factorial(5)
= 5 * factorial(4)
= 5 * 4 * factorial(3)
= 5 * 4 * 3 * factorial(2)
= 5 * 4 * 3 * 2 * factorial(1)
= 5 * 4 * 3 * 2 * 1
= 120

Every recursive function needs a base case — a condition where it stops calling itself. Without it, the function would call itself forever.

Classic example: Fibonacci

fn fibonacci(n: int) -> int {
    if n <= 0 { return 0 }
    if n == 1 { return 1 }
    return fibonacci(n - 1) + fibonacci(n - 2)
}

fn main() {
    var i: int = 0
    while i <= 10 {
        print(fibonacci(i))
        i += 1
    }
    // 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
}

Functions as building blocks

Good programs are built from small, focused functions. Each function does one thing well:

fn celsius_to_fahrenheit(c: float) -> float {
    return c * 9.0 / 5.0 + 32.0
}

fn is_freezing(temp_c: float) -> bool {
    return temp_c <= 0.0
}

fn describe_temperature(c: float) -> String {
    let f: float = celsius_to_fahrenheit(c)
    if is_freezing(c) {
        return "Freezing!"
    }
    if c > 35.0 {
        return "Very hot!"
    }
    return "Comfortable"
}

fn main() {
    print(describe_temperature(0.0))     // Freezing!
    print(describe_temperature(22.0))    // Comfortable
    print(describe_temperature(40.0))    // Very hot!
}

Notice how describe_temperature calls celsius_to_fahrenheit and is_freezing. Functions can call other functions — this is how you build complex programs from simple pieces.

Functions without return

If a function doesn't return anything, you can omit the -> part:

fn say_hello(name: String) {
    print("Hello, " + name)
    // no return statement needed
}

fn main() {
    say_hello("Alice")
}

Exercises

  1. Write a function max(a: int, b: int) -> int that returns the larger of two numbers.
  1. Write a function is_even(n: int) -> bool that returns true if a number is even.
  1. Write a function power(base: int, exp: int) -> int that calculates base raised to the power of exp using a while loop (not recursion).
  1. Write a function count_digits(n: int) -> int that returns how many digits a positive number has. Hint: keep dividing by 10 until you reach 0.
  1. Write a function gcd(a: int, b: int) -> int that computes the greatest common divisor using Euclid's algorithm: if b is 0, return a; otherwise, return gcd(b, a % b).

Summary

Next chapter: Arrays →

← Previous: Control flow Next: Arrays →