OxL Reference

Step 2. Functions

Why#

A function is the basic unit of reuse. In OxL the signature of a function is its contract: the parameter types, the result type and (see step 8) the effects are written in one place. You can therefore read code without looking into function bodies.

The body of a function is an expression: the last expression of a block is the result, return is only needed for an early exit. if and match are expressions too, which is why the language has no ternary operator - it is not needed.

Example#

oxl✓ checked in CI
fn square(x: i32) -> i32  pure => x * x  // pure means no side effects

fn greet(name: str, greeting: str = "Hello", loud: bool = false) -> str  pure {
  let text = "{greeting}, {name}"
  if loud { text.upper() } else { text }  // if is an expression; the last expression of a block is its value
}

// variadic parameter: inside the function xs is a slice
fn sumAll(...xs: i32) -> i32  pure {
  var total = 0
  for x in xs { total += x }
  total
}

fn apply(f: fn(i32) -> i32, x: i32) -> i32  pure => f(x)

fn main() io {
  print("{square(7)}")
  print(greet("Ann"))
  print(greet("Bob", loud: true))  // a named argument
  print("{sumAll(1, 2, 3, 4)}")
  let k = 10
  let addK = (x: i32) => x + k  // a closure captures k
  print("{apply(addK, 5)} {apply(square, 6)}")
}
Output
49
Hello, Ann
HELLO, BOB
10
15 36

Walkthrough#

  • fn square(x: i32) -> i32 pure => x * x - the short form => expression. The word pure means "no side effects": such a function may be called from anywhere.
  • greeting: str = "Hello" - a default value is evaluated on every call where the argument is omitted. Optional parameters are convenient to pass by name: greet("Bob", loud: true). Positional arguments come first, named ones after.
  • ...xs: i32 - a variadic parameter; inside the function it is a slice [i32] that you can walk with for.
  • (x: i32) => x + k - a lambda. It captures k from the surrounding code. A function can be passed as a value: the parameter f: fn(i32) -> i32 accepts both a lambda and the ordinary function square.
  • Signatures of pub/pub(api) functions are written in full; for private functions the result type may be inferred from => expression.

Common mistake: wrong number of arguments#

oxl✓ checked in CI
fn add(a: i32, b: i32) -> i32 => a + b

fn main() {
  let s = add(1)
}
error
arg-count

The compiler names the function and tells how many arguments were expected: arg-count. If a parameter should be optional, give it a default value. A name of a nonexistent named parameter gives named-arg.

Remember#

  • The result is the last expression; return is for early exit.
  • Default values plus named arguments replace function overloading.
  • Lambdas and functions are interchangeable wherever fn(…) -> … is expected.

Next: data: data and enum.

See also

OxL 1.0.0-beta · Documentation version 1.0.0-beta© OxwaldLink · generated from the Standard, the std sources and the guides