← Code Compare

Collections (map/filter/fold)

One tiny pipeline in all five BEAM languages: from [1,2,3,4,5,6], keep the evens, double them, and sum the result (24). Notice how the same trio of operations is spelled differently - Erlang and LFE lean on the lists module, Elixir threads data through the |> pipe with Enum, Gleam composes typed gleam/list functions with a labelled from: accumulator, and Luerl falls back to plain Lua loops since standard Lua ships no higher-order list library.

Show: ErlangElixirGleamLFELuerl
Erlang
-module(collections).
-export([run/0]).

run() ->
    lists:foldl(fun(X, Acc) -> Acc + X end, 0,
        lists:map(fun(X) -> X * 2 end,
            lists:filter(fun(X) -> X rem 2 =:= 0 end,
                [1, 2, 3, 4, 5, 6]))).
%% run() => 24

Erlang reaches for the lists module: filter, then map, then foldl with an accumulator, each taking an anonymous fun. Reading inside-out is the price of having no pipe operator.

Elixir
[1, 2, 3, 4, 5, 6]
|> Enum.filter(fn x -> rem(x, 2) == 0 end)
|> Enum.map(&(&1 * 2))
|> Enum.sum()
# => 24

Elixir threads the list through the |> pipe so each Enum step reads top-to-bottom; &(&1 * 2) is the capture shorthand for a one-argument function, and Enum.sum/1 is the idiomatic fold for addition.

Gleam
import gleam/io
import gleam/int
import gleam/list

pub fn main() {
  let total =
    [1, 2, 3, 4, 5, 6]
    |> list.filter(fn(x) { x % 2 == 0 })
    |> list.map(fn(x) { x * 2 })
    |> list.fold(from: 0, with: fn(acc, x) { acc + x })

  io.println(int.to_string(total))
  // prints: 24
}

Gleam pipes through the typed gleam/list functions; list.fold uses labelled arguments (from: for the initial accumulator, with: for the reducer), and int.to_string is required because the compiler will not implicitly coerce an Int to a String.

LFE
(defmodule collections
  (export (run 0)))

(defun run ()
  (lists:foldl
    (lambda (x acc) (+ acc x))
    0
    (lists:map
      (lambda (x) (* x 2))
      (lists:filter
        (lambda (x) (=:= 0 (rem x 2)))
        '(1 2 3 4 5 6)))))
;; (collections:run) => 24

LFE is Erlang in S-expressions, so it calls the same lists:filter/map/foldl, but with lambda forms and prefix operators like (* x 2). The nesting reads naturally outside-in once you are used to Lisp.

Luerl
local nums = {1, 2, 3, 4, 5, 6}

local total = 0
for _, x in ipairs(nums) do
  if x % 2 == 0 then       -- filter: keep evens
    total = total + x * 2   -- map (double) + fold (sum) in one pass
  end
end

print(total)  --> 24

Standard Lua (what Luerl runs) has no built-in map/filter/fold, so the idiom is a single for ... ipairs loop that filters, doubles, and accumulates in one pass. The % operator and print behave just as in any Lua 5.3/5.4 program.