Skip to main content

Functions — Reusable Code Blocks

Functions let you package code into reusable pieces. Write once, use many times.

Why Functions?

// ❌ Without function - repetitive
print("=== Welcome ===");
print("Hello, Alice!");
print("=== Welcome ===");

print("=== Welcome ===");
print("Hello, Bob!");
print("=== Welcome ===");

// ✅ With function - reusable
fn greet(name) {
print("=== Welcome ===");
print("Hello, ", name, "!");
print("=== Welcome ===");
}

greet("Alice");
greet("Bob");
greet("Charlie");

Output:

=== Welcome ===
Hello, Alice!
=== Welcome ===
=== Welcome ===
Hello, Bob!
=== Welcome ===
=== Welcome ===
Hello, Alice!
=== Welcome ===
=== Welcome ===
Hello, Bob!
=== Welcome ===
=== Welcome ===
Hello, Charlie!
=== Welcome ===

Basic Function Syntax

fn function_name(parameters) {
// body
return value; // optional
}

Function with No Parameters

fn say_hello() {
print("Hello!");
}

say_hello(); // Call the function

Output:

Hello!

Function with Parameters

fn greet(name) {
print("Hello, ", name, "!");
}

greet("Alice"); // Hello, Alice!
greet("Bob"); // Hello, Bob!

Output:

Hello, Alice!
Hello, Bob!

Function with Return Value

fn add(a, b) {
return a + b;
}

let result = add(5, 3);
print(result); // 8

Output:

8

Multiple Parameters

fn rectangle_area(width, height) {
return width * height;
}

print(rectangle_area(5, 3)); // 15
print(rectangle_area(10, 4)); // 40

Output:

15
40

Return Values

Explicit Return

fn max(a, b) {
if (a > b) {
return a;
}
return b;
}

print(max(10, 20)); // 20

Output:

20

Implicit Return (Last Expression)

fn add(a, b) {
a + b // Last expression is returned automatically
}

print(add(2, 3)); // 5

Output:

5

Early Return

fn divide(a, b) {
if (b == 0) {
return "Error: Division by zero";
}
return a / b;
}

print(divide(10, 2)); // 5
print(divide(10, 0)); // Error: Division by zero

Output:

5
Error: Division by zero

Parameters and Arguments

TermMeaning
ParameterVariable in function definition
ArgumentValue passed when calling
fn greet(name, age) { // name, age are parameters
print(name, "is", age, "years old");
}

greet("Alice", 25); // "Alice", 25 are arguments

Output:

Alice is 25 years old

Default Parameters

fn greet(name, greeting = "Hello") {
print(greeting, ", ", name, "!");
}

greet("Alice"); // Hello, Alice!
greet("Bob", "Hi"); // Hi, Bob!

Output:

Hello, Alice!
Hi, Bob!

Scope in Functions

Variables inside a function are local (only exist there):

let global_var = "I'm global";

fn demo() {
let local_var = "I'm local";
print(global_var); // ✅ Can access global
print(local_var); // ✅ Can access local
}

demo();
print(global_var); // ✅ Can access global
// print(local_var); // ❌ Error! local_var doesn't exist here

Output:

I'm global
I'm local
I'm global

Practical Examples

Example 1: Calculator Functions

fn add(a, b) { return a + b; }
fn subtract(a, b) { return a - b; }
fn multiply(a, b) { return a * b; }
fn divide(a, b) {
if (b == 0) return "Error";
return a / b;
}

print("5 + 3 =", add(5, 3)); // 8
print("10 - 4 =", subtract(10, 4)); // 6
print("6 * 7 =", multiply(6, 7)); // 42
print("20 / 4 =", divide(20, 4)); // 5

Output:

5 + 3 = 8
10 - 4 = 6
6 * 7 = 42
20 / 4 = 5

Example 2: String Utilities

fn reverse(text) {
let result = "";
for i in 0..len(text) {
result = text[i] + result;
}
return result;
}

fn is_palindrome(text) {
return text == reverse(text);
}

print(reverse("hello")); // olleh
print(is_palindrome("racecar")); // true
print(is_palindrome("hello")); // false

Output:

olleh
true
false

Example 3: Array Helpers

fn sum_array(arr) {
let total = 0;
for n in arr {
total = total + n;
}
return total;
}

fn average(arr) {
return sum_array(arr) / len(arr);
}

fn find_max(arr) {
let max = arr[0];
for n in arr {
if (n > max) max = n;
}
return max;
}

let scores = [85, 92, 78, 96, 88];
print("Sum:", sum_array(scores)); // 439
print("Avg:", average(scores)); // 87.8
print("Max:", find_max(scores)); // 96

Output:

Sum: 439
Avg: 87.8
Max: 96

Example 4: Recursive Function

A function that calls itself:

fn factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}

print(factorial(5)); // 120 (5*4*3*2*1)

Output:

120
fn fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}

for i in 0..10 {
print(fibonacci(i)); // 0 1 1 2 3 5 8 13 21 34
}

Output:

0
1
1
2
3
5
8
13
21
34

Functions as Values

Functions can be stored in variables and passed around:

fn add(a, b) { return a + b; }
fn multiply(a, b) { return a * b; }

let operation = add;
print(operation(5, 3)); // 8

operation = multiply;
print(operation(5, 3)); // 15

Output:

8
15

Passing Functions to Functions

fn apply_twice(fn, value) {
return fn(fn(value));
}

fn double(x) { return x * 2; }
fn increment(x) { return x + 1; }

print(apply_twice(double, 5)); // 20 (5*2*2)
print(apply_twice(increment, 5)); // 7 (5+1+1)

Output:

20
7

Anonymous Functions (Closures)

let greet = fn(name) {
return "Hello, " + name + "!";
};

print(greet("World")); // Hello, World!

// Short form
let square = fn(x) { x * x; };
print(square(4)); // 16

Output:

Hello, World!
16

Built-in Higher-Order Functions

let numbers = [1, 2, 3, 4, 5];

// map - transform each element
let doubled = numbers.map(fn(x) { return x * 2; });
print(doubled); // [2, 4, 6, 8, 10]

// filter - keep matching elements
let evens = numbers.filter(fn(x) { return x % 2 == 0; });
print(evens); // [2, 4]

// reduce - combine to single value
let sum = numbers.reduce(fn(acc, x) { return acc + x; }, 0);
print(sum); // 15

Output:

[2, 4, 6, 8, 10]
[2, 4]
15

Best Practices

PrincipleDescription
Single responsibilityOne function, one job
Descriptive namescalculate_tax not calc
Small functions10-20 lines max
Avoid side effectsPure functions are easier to test
Document purposeComment what it does, not how

Quick Reference

TaskCode
Define functionfn name(params) { body }
Call functionname(args)
Return valuereturn value or last expression
Default paramfn name(param = default) { }
Anonymous functionfn(params) { body }

Practice Exercise

Create math_utils.adesh:

// 1. Basic operations
fn add(a, b) { return a + b; }
fn subtract(a, b) { return a - b; }
fn multiply(a, b) { return a * b; }
fn divide(a, b) {
if (b == 0) return null;
return a / b;
}

// 2. Advanced
fn power(base, exp) {
let result = 1;
for i in 0..exp {
result = result * base;
}
return result;
}

fn is_even(n) { return n % 2 == 0; }
fn is_odd(n) { return n % 2 != 0; }

// 3. Test them
print("2^8 =", power(2, 8)); // 256
print("Is 42 even?", is_even(42)); // true
print("Is 7 odd?", is_odd(7)); // true

// 4. Calculator using functions
fn calculate(a, op, b) {
if (op == "+") return add(a, b);
if (op == "-") return subtract(a, b);
if (op == "*") return multiply(a, b);
if (op == "/") return divide(a, b);
return "Unknown operator";
}

print(calculate(10, "+", 5)); // 15
print(calculate(10, "/", 0)); // null

Output:

2^8 = 256
Is 42 even? true
Is 7 odd? true
15
null

Summary

You learned:

  • fn name(params) { body } defines a function
  • Call with name(args)
  • return sends value back (last expression auto-returns)
  • Parameters vs arguments
  • Default parameters
  • Local vs global scope
  • Functions as values (first-class)
  • Anonymous functions
  • map, filter, reduce

Next Step

Functions are values too — now let's master higher-order functions (callbacks, closures, and composition)! Continue to Higher-Order Functions