Published 07 Feb, 2025 by Louis Pilfold
Gleam is a type-safe and scalable language for the Erlang virtual machine and JavaScript runtimes. Today Gleam v1.8.0 has been published. Let’s take a look!
Rename variables and arguments
The most desired feature for a long time has probably been “rename” in the language server. I’m happy to announce that the first iteration of this has been implemented! Local variables and function arguments can be renamed. For example, given this code:
pub fn main() {
let wibble = 10
wibble + 1
}
Triggering the “rename” command in your editor with your cursor on wibble
and
then entering my_number
will cause the language server to edit your code like
so:
pub fn main() {
let my_number = 10
my_number + 1
}
It’s not limited to variables that are used a single time, all the uses will be converted as required. This is just the first iteration of this feature, renaming for other things in Gleam code will come in future releases.
Thank you Surya Rose for this long awaited feature!
Erlang documentation integration
Erlang OTP27 added the -doc
attribute, a new standard for adding documentation
to Erlang based code. The documentation for functions with this attribute can be
programmatically accessed, for example using the documentation helper in the
Erlang and Elixir REPLs.
Eshell V15.1.3 (press Ctrl+G to abort, type help(). for help)
1> h(gleam@list, map).
map(List, Fun)
Returns a new list containing only the elements of the first list after the
function has been applied to each one.
Examples
map([2, 4, 6], fn(x) { x * 2 })
// -> [4, 8, 12]
As you can see, Giacomo Cavalieri has added support for this attribute in the Gleam code generator, so Gleam documentation can be accessed like this from any BEAM language. The code is generated in such a fashion that it will continue to work with older version of Erlang/OTP also. Thank you Jak!
Generate function code action
The language server can now generate the definition of functions that do not yet exist. For example if I write the following piece of code:
import gleam/io
pub type Pokemon {
Pokemon(pokedex_number: Int, name: String)
}
pub fn main() {
io.println(to_string(pokemon))
}
Triggering the “generate function” code action on the to_string
function call
will cause the language server to edit the code to add the empty function
definition, including type annotations.
fn to_string(pokemon: Pokemon) -> String {
todo
}
Programmers who write this code “top down” will find this especially convenient. Thank you to Giacomo Cavalieri, a “top down” programmer who I’m pretty sure added this entirely for himself.
Pattern match code action
The language server now suggests a code action to pattern match on a variable. For example, if you have this code:
pub fn main() {
let result = list.first(a_list)
}
Triggering the code action on the result
variable will generate the
following code for you:
pub fn main() {
let result = list.first(a_list)
case result {
Ok(value) -> todo
Error(value) -> todo
}
}
This works with values of any type, adding all the patterns you would need to exhaustively pattern match on them. It also works for function arguments as well as variables. Thank you Giacomo Cavalieri!
More fault tolerant compilation
Fault tolerant compilation is what allows the language server to still help you work with your code even when it is in an invalid state, a feature which is vital for a good experience refactoring or fixing Gleam code.
Surya Rose and Giacomo Cavalieri have improved code analysis to make the compilation of body-less case expressions and function pipelines fault tolerant. This will be extra impactful for autocompletion while writing new code. Thank you both for this!
Result wrapping hints
Gleam uses a result type for error handling instead of exceptions. At times the
programmer may forget to add the Ok
or Error
needed in fallible functions,
so Giacomo Cavalieri has made the
compiler suggest where to add these to solve a type mismatch.
pub fn greet_logged_user() {
use <- bool.guard(when: !logged_in, return: Error(Nil))
"Hello!"
}
error: Type mismatch
┌─ /main.gleam:7:3
│
7 │ "Hello!"
│ ^^^^^^^^ Did you mean to wrap this in an `Ok`?
Expected type:
Result(a, Nil)
Found type:
String
Thank you Jak!
gleam deps tree
Gleam uses the Hex, the package manager for the BEAM ecosystem. The build tool will automatically download and compile appropriate versions of the dependencies your project needs, along with their dependencies.
The new gleam deps tree
command can be used to view the relationship between
all your dependencies.
$ gleam deps tree
project_a v1.0.0
├── package_b v0.52.0
└── package_c v1.2.0
└── package_b v0.52.0
The --package
option can be used to view just a portion of the dependency
tree.
$ gleam deps tree --package package_c
package_c v1.2.0
└── package_b v0.52.0
And the --invert
option can be used to view all paths from a package to the
root of the project, which can be very useful for understanding why a particular
package version was included in the project.
$ gleam deps tree --invert package_b
package_b v0.52.0
├── package_c v1.2.0
│ └── project_a v1.0.0
└── project_a v1.0.0
Thank you Ramkarthik Krishnamurthy for this new command!
HTML documentation hotkeys
Gleam can generate HTML documentation for your code when you run gleam docs
build
, and it will automatically generate and publish this documentation to
HexDocs when publishing a package.
Sambit Sahoo has added hotkeys, making the
search input be focused when cmd/ctrl + k
, s
or /
is pressed. Thank you!
Invalid project name correction
Gleam project names have to be all lowercase letters and underscores and
numbers, and not collide with any Gleam keywords. The glean new
command would
reject invalid names, but now it will suggest a valid name instead and ask if
the programmer would like to use that instead.
$ gleam new type
We were not able to create your project as `type` is a reserved word in
Gleam.
Would you like to name your project 'type_app' instead? [y/n]:
Thank you Diemo Gebhardt for this!
Better “fill labels” code action
The language server can now fill in the labels of any function call, even when only some of the arguments are provided. For example:
import gleam/string
pub fn main() {
string.replace("wibble")
}
Will be completed to:
import gleam/string
pub fn main() {
string.replace("wibble", each: todo, with: todo)
}
Thank you Giacomo Cavalieri!
And the rest
And thank you to the bug fixers and error message improvers: Giacomo Cavalieri, Jiangda Wang, John Strunk, Kasim, shayan, Surya Rose, and yoshi
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 Giacomo Cavalieri specifically on GitHub Sponsors.
Thank you to all our sponsors! And especially our top sponsor: Lambda.
- 00bpa
- Aaron Gunderson
- Abdulrhman Alkhodiry
- 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
- Antoni
- Arthur Weagel
- Arya Irani
- Azure Flash
- Barry Moore
- Bartek Górny
- Ben Martin
- Ben Marx
- Ben Myles
- Benjamin Kane
- Benjamin Peinhardt
- bgw
- Bjarte Aarmo Lund
- Brad Mehder
- brettkolodny
- Brian Dawn
- Brian Glusman
- Bruce Williams
- Bruno Michel
- bucsi
- Cam Ray
- Cameron Presley
- Carlo Munguia
- Carlos Saltos
- Chad Selph
- Charlie Duong
- Charlie Govea
- Chaz Watkins
- 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
- CodeCrafters
- Coder
- Cole Lawrence
- Colin
- Comamoca
- Constantin (Cleo) Winkler
- Corentin J.
- Daigo Shitara
- Damir Vandic
- Dan Dresselhaus
- Danielle Maywood
- Danny Arnold
- Danny Martini
- Dave Lucia
- David Bernheisel
- David Cornu
- David Sancho
- Dennis Dang
- dennistruemper
- Diemo Gebhardt
- Dillon Mulroy
- Dima Utkin
- Dmitry Poroh
- DoctorCobweb
- Donnie Flood
- ds2600
- Dylan Carlson
- Éber Freitas Dias
- Ed Hinrichsen
- Edon Gashi
- eeeli24
- 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 Mayer
- Fernando Farias
- Filip Figiel
- Florian Kraft
- Francis Hamel
- frankwang
- G-J van Rooyen
- Gabriel Vincent
- Geir Arne Hjelle
- Georg Hartmann
- George
- ggobbe
- Giacomo Cavalieri
- Giovanni Kock Bonetti
- Graham Vasquez
- grotto
- Guilherme de Maio
- Guillaume Heu
- Guillaume Hivert
- H-274
- Hammad Javed
- Hannes Nevalainen
- Hannes Schnaitter
- Hans Raaf
- Hayes Hundman
- Hayleigh Thompson
- Hazel Bachrach
- Henning Dahlheim
- Henrik Tudborg
- Henry Firth
- Henry Warren
- Heyang Zhou
- human154
- Humberto Piaia
- Iain H
- Ian González
- Ian M. Jones
- Igor Montagner
- Igor Rumiha
- ILLIA NEGOVORA
- Ingrid
- inoas
- Isaac
- Isaac Harris-Holt
- Isaac McQueen
- Ismael Abreu
- István Bozsó
- Ivar Vong
- Jacob Lamb
- Jake Cleary
- James Birtles
- James MacAulay
- Jan Pieper
- Jan Skriver Sørensen
- Jean-Luc Geering
- Jen Stehlik
- jiangplus
- Jimpjorps™
- Joey Kilpatrick
- Joey Trapp
- Johan Strand
- John Björk
- John Gallagher
- John Pavlick
- John Strunk
- Jojor
- Jon Lambert
- Jonas E. P
- Jonas Hedman Engström
- jooaf
- Joseph Lozano
- Joshua Steele
- 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 G.
- Leandro Ostera
- Lee Jarvis
- Leon Qadirie
- Leonardo Donelli
- lidashuang
- Lily Rose
- Loïc Tosser
- Lucas Pellegrinelli
- Lukas Bjarre
- Lukas Meihsner
- 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
- Matias Klemola
- Matt Champagne
- Matt Heise
- Matt Mullenweg
- Matt Robinson
- Matt Savoia
- Matt Van Horn
- Matthew Whitworth
- Max McDonnell
- max-tern
- metame
- METATEXX GmbH
- Metin Emiroğlu
- Michael Duffy
- Michael Jones
- Michael Mazurczak
- Mikael Karlsson
- Mike
- Mike Roach
- Mikey J
- MoeDev
- MzRyuKa
- n8n - Workflow Automation
- Natanael Sirqueira
- Nathaniel Knight
- Nayuki
- NFIBrokerage
- Nicholas Moen
- Nick Chapman
- Nick Reynolds
- Nicklas Sindlev Andersen
- NicoVIII
- Niket Shah
- Ninaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- NineFX
- Nomio
- Ocean
- Olaf Sebelin
- OldhamMade
- Oleg Yuzvik
- Oliver Medhurst
- Oliver Tosky
- optizio
- Osman Cea
- PastMoments
- Patrick Wheeler
- Paul Guse
- Pawel Biernacki
- Pedro Correa
- Pete Jodo
- Peter Rice
- Philpax
- Pierrot
- Piotr Szlachciak
- 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
- Rob
- 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 Weber
- Scott Wey
- Scott Zhu Reeves
- Sean Jensen-Grey
- Sean Roberts
- Sebastian Porto
- sekun
- Seve Salazar
- Shane Poppleton
- Shuqian Hon
- Sigma
- Simone Vittori
- Stefan
- Stefan Hagen
- Steinar Eliassen
- Stephen Belanger
- Steve Powers
- Strandinator
- Sunil Pai
- Sławomir Ehlert
- Theo Harris
- Thomas
- Thomas Coopman
- Thomas Ernst
- Tim Brown
- Timo Sulg
- Tom Schuster
- Tomasz Kowal
- tommaisey
- Travis Johnson
- Tristan de Cacqueray
- Tristan Sloughter
- tymak
- Uni Huang
- upsidedowncake
- Valerio Viperino
- Vic Valenzuela
- Victor Rodrigues
- Viv Verner
- Volker Rabe
- Weizheng Liu
- wheatfox
- Willyboar
- Wilson Silva
- Xucong Zhan
- Yamen Sader
- Yasuo Higano
- yoshi~
- Zsombor Gasparin
- ~1814730
- ~1847917
- ~1867501
This release is dedicated to the memory of my grandfather, Len Pilfold, who passed away in January.