Functions

Declaring and calling functions in Chasm with def and defp.

def vs defp

def declares a public function visible to the host engine and other modules. defp declares a private function only callable within the same file:

# Public, the engine can call this
def on_tick(dt :: float) do
  tick(@speed, dt)
end

# Private, only callable within this file
defp tick(speed :: float, dt :: float) do
  @player_x = @player_x + speed * dt
end

Parameters

Every parameter requires a type annotation with :::

defp add(a :: int, b :: int) :: int do
  return a + b
end

There are no default parameter values, use multiple functions or an explicit check instead.

Return Type

Private functions (defp) require an explicit return type annotation when they return a value. Public functions (def) may omit it:

defp area(w :: float, h :: float) :: float do
  w * h
end

The last expression in a function body is the implicit return value. return is optional but can be used to exit early:

defp clamp_score(s :: int) :: int do
  if s < 0 do return 0 end
  if s > 999 do return 999 end
  return s
end

Multiple Return Values

A function can return more than one value by listing them after return, separated by commas. The return type annotation uses a tuple form :: (T, T):

defp minmax(a :: int, b :: int) :: (int, int) do
  if a < b do
    return a, b
  else
    return b, a
  end
end

def main() do
  lo, hi = minmax(7, 3)
  print(lo)   # 3
  print(hi)   # 7
end

Recursion

Functions can call themselves. Chasm has no stack overflow protection, so keep recursion depth bounded:

defp fib(n :: int) :: int do
  if n <= 1 do
    return n
  end
  return fib(n - 1) + fib(n - 2)
end

def main() do
  print(fib(10))   # 55
end

Calling Functions

Call a function by name with arguments in parentheses:

result = add(3, 4)
lo, hi = minmax(9, 2)

The Pipe Operator with Functions

The |> operator passes a value as the first argument to the next function. It chains well with defp helpers:

defp double(x :: float) :: float do x * 2.0 end
defp cap(x :: float) :: float do clamp(x, 0.0, 100.0) end

def main() do
  result = 30.0 |> double() |> cap()
  print(result)   # 60.0
end

Entry Points

The engine calls specific def functions by convention:

FunctionWhen called
def on_init()Once, before the first tick
def on_tick(dt :: float)Every frame, with elapsed time in seconds
def on_draw()Every frame, after on_tick
def main()Standalone scripts (no engine)