Functions in Depth
Functions in Clean Language are strictly typed — the compiler knows exactly what each function accepts and returns. This makes composition safe: when you call one function's output as another's input, the compiler verifies the types match.
Functions call other functions freely — build complex behavior from simple pieces:
functions:\n integer clamp(integer value, integer min_val, integer max_val)\n if value < min_val\n return min_val\n if value > max_val\n return max_val\n return value\n\n string progress_bar(integer percent)\n integer clamped = clamp(percent, 0, 100)\n integer bars = clamped / 10\n string filled = ""\n iterate i in 0 to bars - 1\n filled = filled + "#"\n string empty = ""\n iterate i in 0 to (10 - bars) - 1\n empty = empty + "-"\n return "[" + filled + empty + "] " + clamped.toString() + "%"\n\nstart:\n print(progress_bar(30))\n print(progress_bar(75))\n print(progress_bar(110))[###-------] 30%\n[#######---] 75%\n[##########] 100%progress_bar calls clamp to enforce safe bounds, then builds the bar string. The typed parameters mean calling clamp with a string argument is a compile error. Multiple returns in different branches are fine — whichever branch executes returns from the function.
Functions that return boolean answer a yes/no question — perfect for if conditions:
functions:\n boolean is_valid_email(string email)\n if email.length() < 5\n return false\n if email.contains("@") == false\n return false\n if email.contains(".") == false\n return false\n return true\n\n string check_email(string email)\n if is_valid_email(email)\n return email + " looks valid"\n return email + " is not a valid email"\n\nstart:\n print(check_email("alice@example.com"))\n print(check_email("notanemail"))\n print(check_email("short@x"))alice@example.com looks valid\nnotanemail is not a valid email\nshort@x is not a valid emailis_valid_email returns boolean, so check_email can use it directly as an if condition. This is Clean Language's idiom for validation: extract the check into a boolean function, then call it where needed. The return type makes the function's intent obvious.
Quick recap
- Functions call other functions freely — compose behavior from simple, testable pieces
- Multiple return statements in different branches are allowed
- Boolean functions answer yes/no questions and work directly as if conditions
- Typed parameters are enforced at compile time — wrong argument types are caught early