Published 14 April, 2025 by Louis Pilfold
Gleam is a type-safe and scalable language for the Erlang virtual machine and JavaScript runtimes. Today Gleam v1.10.0 has been published. Here's what's new:
Project-wide call reference graph
The compiler has been upgraded to retain more information about the types
and values and how they reference each other in Gleam programs. With this
information the language server (which is included within the gleam
binary)
now provides the "find references" feature, so you can find everywhere in your
project where a type or value is used.
The additional information has also been used to improve the "rename" language server feature. Previously only module-local types and values could be renamed, but now renaming can be performed across all modules in a project.
Lastly the compiler's unused-code detection has been greatly improved, fixing some situations in which it would fail to detect it all previously.
Thank you to Surya Rose for implementing this! It is probably our most anticipated addition within the community!
Improved exhaustiveness analysis
Gleam's compiler performs exhaustiveness analysis, ensuring that all possible variants of the value are handled in flow control, and that there are no redundant cases which are not reachable due to previous cases.
Giacomo Cavalieri has spent the time since the previous release studying the academic literature on the complex subject of exhaustiveness checking to bring a variety of improvements to our implementation. The first of these changes has made it into this release: string pattern analysis. Previously only rudamentary analysis was performed on strings, and unreachable string patterns could not be detected.
case a_string {
"Hello, " <> name -> name
"Hello, Jak" -> "Jak"
_ -> "Stranger"
}
In this code the first pattern matches all the values that the second pattern matches, so the second pattern is not reachable. The compiler now emits this warning:
warning: Unreachable case clause
┌─ /src/greet.gleam:7:5
│
7 │ "Hello, Jak" -> "Jak"
│ ^^^^^^^^^^^^^^^^^^^^^
This case clause cannot be reached as a previous clause matches the same
values.
Hint: It can be safely removed.
Thank you Giacomo! Excellent work!
Alongside that the compiler now emits a warning when using let assert
to
assert a value whose variant has already been inferred, such as in this code:
let e = Error("Some error")
let assert Ok(_) = e // warning: Pattern will never match
Thank you Surya Rose!
Operator analysis improvements
Gleam's compiler is fault tolerant, meaning that when an error is encountered in the code it does not stop immediately, instead it shows the error to the programmer, makes a best-effort attempts to recover and continue analysing the rest of the code. This behaviour is vital for the langauge server to have information about the code even when it's in an invalid state.
The analysis of binary operators such as +
and ==
have been improved so
that both sides will be checked even in the presence errors. This improves
language server information in some situations, and it also enables improved
error messages.
Gleam doesn't have operator overloading or interfaces, so each operator works
with a specific type. For example +
is only for adding ints, and string
concatenation is done with the <>
operator. Previously the error message for
the wrong operator would point to the value and say it is of the wrong type,
but now it points to the operator itself and tells you what the correct
operator would be:
error: Type mismatch
┌─ /src/wibble.gleam:2:13
│
2 │ "Hello, " + "Lucy"
│ ^ Use <> instead
The + operator can only be used on Ints.
To join two strings together you can use the <> operator.
The language server willl also offer a code action to fix the error for you in your editor.
pub fn main() {
"Hello, " + "Jak"
//^^^^^^^^^^^^^^^^^ When hovering anywhere over here
}
Triggering the code action would fix the compilation error by using the
correct <>
operator instead of +
:
pub fn main() {
"Hello, " <> "Jak"
}
Thank you Giacomo Cavalieri!
Bit array improvements
Gleam's bit array literal syntax provides a powerful and convenient way to construct and parse binary data.
It is fully supported when targeting the Erlang virtual machine, but some bit
array literals were not fully supported when targeting JavaScript.
Surya Rose has added support for the
unit
option to control the units of the size
option, and
Richard Viney has added support for 16-bit
floats.
Giacomo Cavalieri has made it possible
to omit the :float
option when used with float literals, as the intention is
unambiguous.
These two literals are now equivalent, while previously the former would be a
type error due to lacking sufficient annotations.
<<1.11>>
<<1.11:float>>
Thank you Surya, Richard, and Giacomo!
JavaScript codegen performance improvements
Surya Rose has improved the JavaScript code generation to make the code run faster. Where possible the compiler restructures code to no longer use JavaScript "immediately invoked function expressions", removing the overhead of allocating and then calling these functions.
This is the first of a series of JavaScript performance improvements we are currently working on, and our initial benchmarks show they will be impactful, improving the performance of all Gleam programs that compile to JavaScript without any modification to the programs themeselves.
Thank you Surya!
Cross platform deployment artefacts
BEAM bytecode is portable. You can compile your Erlang, Elixir, or Gleam program on one machine and run it on another with a different operating system and processor architecture.
One annoyance if you were doing this with Gleam was that the gleam export erlang-shipment
command would try to be clever and give you an entrypoint script for the
operating system you are currently using, so if you compiled on Windows to run
on Linux then you would be missing the POSIX shell entrypoint script.
Greg Burri has resolved this problem by having the build tool include all entrypoint scripts, regardless of the operating system used to build the artefact. Thank you Greg!
Package information export
Rodrigo Álvarez has created the gleam export package-information
command, which will write information about a Gleam package to file in JSON
format. This information may be useful to other build tools that wish to
compile Gleam code, and Rodrigo is exploring adding support for Gleam
dependencies to Elixir's Mix build tool.
Thank you Rodrigo! This will be especially exciting for Elixir programmers as many folks use Gleam and Elixir together.
Fill unused fields code action
The language server can now offer a code action to replace a ..
in a pattern
with all the fields that it was being used to ignore. For example triggering
the code action on this code:
pub type Pokemon {
Pokemon(id: Int, name: String, moves: List(String))
}
pub fn main() {
let Pokemon(..) = todo
// ^ If you put your cursor here
}
Would result in the code being edited like so:
pub type Pokemon {
Pokemon(id: Int, name: String, moves: List(String))
}
pub fn main() {
let Pokemon(id:, name:, moves:) = todo
}
Thank you Giacomo Cavalieri!
Improved JSON encoder generation code action
The function generated by the "Generate JSON encoder" code action will now fail to compile if the type has new fields added. The motivation for this may not be immediately clear, so let's dig into that a little.
Gleam's development philosophy is to use static analysis, editor tooling, and other forms of computer assistance to reduce the mental load for the programmer as much as possible. With the previous design if the data type definition was edited the programmer would have to remember about the existance of the JSON encoder, making it possible to forget and accidentally introduce a bug. With the new behaviour this mistake is no longer possible.
Here is an example of a type and the encoder function that the language server
will now generate for it. Note the new pattern matching with let
.
type Person {
Person(name: String, age: Int)
}
fn encode_person(person: Person) -> json.Json {
let Person(name:, age:) = person
json.object([
#("name", json.string(name)),
#("age", json.int(age)),
])
}
Thank you Surya Rose!
Remove echo code action
Gleam has the echo
keyword for debug printing. It's convenient for quickly
understanding runtime behaviour of code, but it should never be included in
production code and the build tool will refuse to publish code that uses it.
The language server now offers a code action to remove all echo
s in a
module. For example:
pub fn main() {
echo 1 + 2
}
Triggering the code action would remove the echo
:
pub fn main() {
1 + 2
}
Thank you Giacomo Cavalieri!
Extract constant code action
The language server now offers the option to lift non-dynamic expressions into constants. If the code action is run on the list literal here:
const lucy = "Lucy"
const nubi = "Nubi"
pub fn main() {
list.each([lucy, nubi, "Biffy"], io.println)
}
The code is updated like so:
const lucy = "Lucy"
const nubi = "Nubi"
const values = [lucy, nubi, "Biffy"]
pub fn main() {
list.each(values, io.println)
}
Thank you Matias Carlander!
Wrap in block code action
The language server will offer to wrap assignment or case clause values in blocks. This is is a convenience for when adding more expressions to some existing code that previous only had one expression, making everyday Gleam editing that little bit easier.
For example, with this code:
pub fn f(pokemon_type: PokemonType) {
case pokemon_type {
Water -> soak()
// ^^^^^^ Cursor within this expression
Fire -> burn()
}
}
Triggering the code action results in the code being updated like so:
pub fn f(pokemon_type: PokemonType) {
case pokemon_type {
Water -> {
soak()
}
Fire -> burn()
}
}
Thank you Matias Carlander!
Security and compliance
Gleam's container images now contain Software Bill of Materials (SBoM) and Supply-chain Levels for Software Artifacts (SLSA) Provenance information.
This will greatly help with security audits and compliance of software written with Gleam, and is part of an ongoing effort to evidence production readiness and promote Gleam adoption within enterprise. This is well timed, as Gleam has just featured in the Thoughtworks technology radar for the first time!
Thank you to Jonatan Männchen and the Erlang Ecosystem Foundation for this and their ongoing support of Gleam and Gleam companies.
And the rest
And thank you to the bug fixers and experience polishers: Alexander Keleschovsky, Drew Olson, Giacomo Cavalieri, Louis Pilfold, Matias Carlander, Sakari Bergen, Sam Zanca, Samuel Cristobal, and Surya Rose.
For full details of the many fixes and improvements they've implemented see the changelog.
A call for support
Gleam is not owned by a corporation; instead it is entirely supported by sponsors, most of which contribute between $5 and $20 USD per month, and Gleam is my sole source of income.
We have made great progress towards our goal of being able to appropriately pay the core team members, but we still have further to go. Please consider supporting the project or core team members Giacomo Cavalieri and Surya Rose on GitHub Sponsors.
Thank you to all our sponsors! And especially our top sponsor: Lambda.
- Aaron Gunderson
- Abel Jimenez
- ad-ops
- Adam Brodzinski
- Adam Johnston
- Adam Wyłuda
- Adi Iyengar
- Adrian Mouat
- Ajit Krishna
- Aleksei Gurianov
- Alembic
- Alex
- Alex Houseago
- Alex Manning
- Alex Viscreanu
- Alexander Koutmos
- Alexander Stensrud
- Alexandre Del Vecchio
- Ameen Radwan
- Andrea Bueide
- AndreHogberg
- Antharuu
- Anthony Khong
- Anthony Maxwell
- Anthony Scotti
- Arthur Weagel
- Arya Irani
- Azure Flash
- Barry Moore
- Bartek Górny
- Ben Martin
- Ben Marx
- Ben Myles
- Benjamin Kane
- Benjamin Moss
- bgw
- Bjarte Aarmo Lund
- Bjoern Paschen
- Borislav Rangelov
- Brad Mehder
- Brendan P.
- brettkolodny
- Brian Dawn
- Brian Glusman
- Bruce Williams
- Bruno Michel
- bucsi
- Cam Ray
- Cameron Presley
- Carlo Munguia
- Carlos Saltos
- Chad Selph
- Charlie Duong
- Charlie Govea
- Chew Choon Keat
- Chris Donnelly
- Chris King
- Chris Lloyd
- Chris Ohk
- Chris Rybicki
- Christopher David Shirk
- Christopher De Vries
- Christopher Dieringer
- Christopher Jung
- Christopher Keele
- CJ Salem
- clangley
- Clifford Anderson
- Coder
- Cole Lawrence
- Colin
- Comamoca
- Comet
- Constantin (Cleo) Winkler
- Corentin J.
- Daigo Shitara
- Damir Vandic
- Dan Dresselhaus
- Dan Strong
- Danielle Maywood
- Danny Arnold
- Danny Martini
- Dave Lucia
- David Bernheisel
- David Cornu
- David Sancho
- Dennis Dang
- dennistruemper
- Diemo Gebhardt
- Dillon Mulroy
- Dima Utkin
- DoctorCobweb
- Donnie Flood
- Dylan Anthony
- Dylan Carlson
- Ed Hinrichsen
- Edon Gashi
- Eileen Noonan
- eli
- Emma
- EMR Technical Solutions
- Endo Shogo
- Eric Koslow
- Erik Terpstra
- erikareads
- ErikML
- erlend-axelsson
- Ernesto Malave
- Ethan Olpin
- Evaldo Bratti
- Evan Johnson
- evanasse
- Fabrizio Damicelli
- Fede Esteban
- Felix
- Fernando Farias
- Filip Figiel
- Florian Kraft
- Francis Hamel
- frankwang
- G-J van Rooyen
- Gabriel Vincent
- Gavin Panella
- Geir Arne Hjelle
- Georg Hartmann
- George
- Georgi Martsenkov
- ggobbe
- Giacomo Cavalieri
- Giovanni Kock Bonetti
- Graham Vasquez
- Grant Everett
- Guilherme de Maio
- Guillaume Heu
- Guillaume Hivert
- Hammad Javed
- Hannes Nevalainen
- Hannes Schnaitter
- Hans Raaf
- Hayleigh Thompson
- Hazel Bachrach
- Henning Dahlheim
- Henrik Tudborg
- Henry Warren
- Heyang Zhou
- Hubert Małkowski
- human154
- Humberto Piaia
- Iain H
- Ian González
- Ian M. Jones
- Igor Montagner
- inoas
- Isaac
- Isaac Harris-Holt
- Isaac McQueen
- István Bozsó
- Ivar Vong
- Jacob Lamb
- Jake Cleary
- Jake Wood
- Jakob Ladegaard Møller
- James Birtles
- James MacAulay
- Jan Pieper
- Jan Skriver Sørensen
- Jean Niklas L'orange
- Jean-Adrien Ducastaing
- Jean-Luc Geering
- Jean-Marc QUERE
- Jen Stehlik
- Jerred Shepherd
- jiangplus
- Jimpjorps™
- Joey Kilpatrick
- Joey Trapp
- Johan Strand
- John Björk
- John Pavlick
- John Strunk
- Jojor
- Jon Lambert
- Jonas E. P
- Jonas Hedman Engström
- jooaf
- Joseph Lozano
- Joshua Steele
- Julian Hirn
- Julian Lukwata
- Julian Schurhammer
- Justin Lubin
- Jérôme Schaeffer
- Kemp Brinson
- Kero van Gelder
- Kevin Schweikert
- Kramer Hampton
- Kritsada Sunthornwutthikrai
- Kryštof Řezáč
- Krzysztof Gasienica-Bednarz
- Leandro Ostera
- Lee Jarvis
- Leon Qadirie
- Leonardo Donelli
- Lexx
- lidashuang
- Lily Rose
- liv
- Loïc Tosser
- Lucas Pellegrinelli
- Lukas Bjarre
- Luke Amdor
- Luna
- Manuel Rubio
- Marcos
- marcusandre
- Mariano Uvalle
- Marius Kalvø
- Mark Holmes
- Mark Markaryan
- Markéta Lisová
- Martijn Gribnau
- Martin Janiczek
- Martin Poelstra
- Martin Rechsteiner
- martonkaufmann
- Matt Champagne
- Matt Heise
- Matt Mullenweg
- Matt Robinson
- Matt Savoia
- Matt Van Horn
- Matthew Jackson
- Matthew Whitworth
- Max McDonnell
- metame
- METATEXX GmbH
- Metin Emiroğlu
- Michael Duffy
- Michael Jones
- Michael Mazurczak
- Michael McClintock
- Mikael Karlsson
- Mike Roach
- Mikey J
- MoeDev
- MzRyuKa
- n8n - Workflow Automation
- Natanael Sirqueira
- Nathaniel Knight
- NFIBrokerage
- Nick Chapman
- Nick Reynolds
- Nicklas Sindlev Andersen
- NicoVIII
- Niket Shah
- Nikolai Steen Kjosnes
- NineFX
- Nomio
- Ocean
- Olaf Sebelin
- OldhamMade
- Oliver Medhurst
- Oliver Tosky
- optizio
- Patrick Wheeler
- Paul Guse
- Pawel Biernacki
- Pedro Correa
- Pete Jodo
- Peter Rice
- Philpax
- Pierrot
- Qdentity
- Race Williams
- Rasmus
- Ray
- Raúl Chouza
- re.natillas
- Redmar Kerkhoff
- Reilly Tucker Siemens
- Renato Massaro
- Renovator
- Richard Viney
- Rico Leuthold
- Rintaro Okamura
- Ripta Pasay
- Robert Attard
- Robert Ellen
- Robert Malko
- Rodrigo Álvarez
- Ronan Harris
- Rotabull
- Rupus Reinefjord
- Ruslan Ustitc
- Ryan Moore
- Sam Aaron
- Sam Zanca
- sambit
- Sammy Isseyegh
- Savva
- Saša Jurić
- Scott Trinh
- Scott Wey
- Scott Zhu Reeves
- Sean Cribbs
- Sean Jensen-Grey
- Sean Roberts
- Sebastian Porto
- sekun
- Seve Salazar
- Shane Poppleton
- Shuqian Hon
- Sigma
- simone
- Stefan
- Stefan Hagen
- Steinar Eliassen
- Stephen Belanger
- Steve Powers
- Strandinator
- Sławomir Ehlert
- Theo Harris
- Thomas
- Thomas Coopman
- Thomas Ernst
- Tim Brown
- Timo Sulg
- Tom Schuster
- Tomasz Kowal
- tommaisey
- Tristan de Cacqueray
- Tristan Sloughter
- Tudor Luca
- tymak
- upsidedowncake
- Valerio Viperino
- Vassiliy Kuzenkov
- Vic Valenzuela
- Victor Rodrigues
- Viv Verner
- Volker Rabe
- Walton Hoops
- Weizheng Liu
- wheatfox
- Willyboar
- Wilson Silva
- Xucong Zhan
- Yamen Sader
- Yasuo Higano
- yoshi~
- Zsombor Gasparin
- ZWubs
- ~1814730
- ~1847917
- ~1867501
- Éber Freitas Dias