← Code Compare

Functions

Functions are the heart of every BEAM language, and most of them lean on pattern matching across multiple clauses rather than if/else ladders. Notice how Erlang, Elixir, and LFE dispatch on guards (when) while statically typed Gleam exhaustively matches with case, and Lua (Luerl) falls back to ordinary conditionals since it has no clauses. Each example also shows a higher-order use - passing the function to a list operation like map - which is the everyday way you reuse logic on the BEAM.

Show: ErlangElixirGleamLFELuerl
Erlang
-module(classify).
-export([classify/1, demo/0]).

%% Multiple clauses with guards; tested top-to-bottom.
classify(N) when N < 0 -> negative;
classify(0)            -> zero;
classify(_N)           -> positive.

demo() ->
    %% Higher-order: hand classify/1 to lists:map as a fun.
    lists:map(fun classify/1, [-3, 0, 7]).
    %% => [negative, zero, positive]

Erlang defines one function as several clauses separated by ;, each with its own head and optional when guard; fun classify/1 turns it into a value you can pass to lists:map/2.

Elixir
defmodule Classify do
  # Each `def` clause matches a pattern or guard, in order.
  def classify(n) when n < 0, do: :negative
  def classify(0), do: :zero
  def classify(_n), do: :positive
end

# Higher-order: capture the function with &/1 and pipe through Enum.map.
[-3, 0, 7]
|> Enum.map(&Classify.classify/1)
# => [:negative, :zero, :positive]

Elixir spreads a function over multiple def clauses with when guards, then uses the &Module.fun/1 capture and the |> pipe to map it over a list.

Gleam
import gleam/list
import gleam/order
import gleam/int

pub type Sign {
  Negative
  Zero
  Positive
}

// One clause; an exhaustive `case` over the comparison result.
pub fn classify(n: Int) -> Sign {
  case int.compare(n, 0) {
    order.Lt -> Negative
    order.Eq -> Zero
    order.Gt -> Positive
  }
}

pub fn main() {
  // Higher-order: pass classify as a first-class function to list.map.
  [-3, 0, 7]
  |> list.map(classify)
  |> echo
  // => [Negative, Zero, Positive]
}

Gleam has a single pub fn whose case must be exhaustive, returning a sound custom type instead of an atom; classify is passed by name to list.map with no null or exceptions in sight.

LFE
(defmodule classify
  (export (classify 1) (demo 0)))

;; Multiple clauses with guards inside one defun.
(defun classify
  ((n) (when (< n 0)) 'negative)
  ((0) 'zero)
  ((_n) 'positive))

(defun demo ()
  ;; Higher-order: #'classify/1 grabs the function as a value.
  (lists:map #'classify/1 (list -3 0 7)))
  ;; => (negative zero positive)

LFE writes the clauses as parenthesised pattern lists with (when ...) guards inside a single defun, and #'classify/1 is the Lisp reader macro for a function reference passed to lists:map.

Luerl
-- Lua has no clauses or guards, so branch with if/elseif.
local function classify(n)
  if n < 0 then
    return "negative"
  elseif n == 0 then
    return "zero"
  else
    return "positive"
  end
end

-- Higher-order: functions are values; map one over a table.
local function map(fn, t)
  local out = {}
  for i, v in ipairs(t) do out[i] = fn(v) end
  return out
end

for _, s in ipairs(map(classify, { -3, 0, 7 })) do
  print(s)
end
-- => negative  zero  positive

Lua expresses the same logic with a plain if/elseif/else since it lacks pattern matching, but functions are still first-class values, so a hand-rolled map can take classify as an argument.