Abstract
For those who don't know, Gleam is a high-level, statically-typed functional language that runs on BEAM - Erlang's VM. It has been voted as 2nd most admired language - right after Rust - in SO dev survey in 2025. In March 2024, version 1.0.0 was released, which indicates that authors consider the language somewhat mature. However is it practical to write larger projects with Gleam?
Motivation
I've decided to write a classic game of life in Gleam. This project usually takes just several hours to complete even in an unfamiliar language, but is complex enough to use loops and matrices. This post lists my thoughts after finishing this project.
Implementation
Few words about development experience with Gleam - it has all the necessities available, like VSCode plugin, LSP, etc. It's also easy to set up with good tutorials available, so I won't be touching this topic here.
Stdlib - batteries not included
First of all - there are no 2d arrays aka matrices in gleam stdlib. Fortunately, it should be easy to implement them yourself:
pub type Arr2d(a) =
glearray.Array(glearray.Array(a))
Using glearray instead of gleam/list should allow for more efficient indexed access. But also, we need to implement functions for getting and setting elements in the array:
pub fn get_el(arr: Arr2d(Bool), x: Int, y: Int) -> Result(Bool, Nil) {
case glearray.get(arr, at: y) {
Ok(row) -> glearray.get(row, at: x)
Error(_) -> Error(Nil)
}
}
pub fn set_el(arr: Arr2d(Bool), x: Int, y: Int, v: Bool) -> Arr2d(Bool) {
case glearray.get(arr, at: y) {
Ok(row) ->
case glearray.copy_set(row, at: x, value: v) {
Ok(new_row) ->
glearray.copy_set(arr, at: y, value: new_row)
|> result.unwrap(arr)
Error(_) -> arr
}
Error(_) -> arr
}
}
Not a complicated code by any means, but you're forced to write it if you want to use matrices. Any mainstream general-purpose language I can think of - including functional ones like F# - supports matrices of the box.
Loops
Gleam being a functional language, famously doesn't have them. You can rewrite you code to use recursion instead, but it arguably makes your code much harder to reason about. So you probably will use something like this to emulate for loop:
list.range(0, count - 1)
|> list.each(fn(e) {
echo e
})
Is it easier to read than F# code?
for e in 0 .. count do
printfn "%d" e
You decide.
Of course, if you need to do some computations in the loop, you'll need to use something like list.fold instead.
Auto-formatting
Just like Golang, Gleam auto-formats your code. And it's not customizable by design. While I can see the rationale, I don't believe in one-size-fits-all approach. It would be much better to have a set of default options you can customize rather than be told how your code should look like.
Conclusion
While this article may paint an overly negative picture of Gleam, I actually somewhat like the language. It's not a bad language to use if your task is iterating over some collections or writing a simple parser. It also can be used to teach functional languages, being much simpler and less intimidating than Haskell, Scala and others.
Top comments (0)