Published 02 Aug, 2024 by Louis Pilfold
Gleam is a type safe and scalable language for the Erlang virtual machine and JavaScript runtimes. Today Gleam v1.4.0 has been published, so let’s go over all that’s new.
A shorthand syntax for labels
Gleam’s labelled arguments are a way to give a parameter a name that can be used
at the call site. These serve as documentation and to make code easier to read and
modify. Here the function date
takes 3 labelled arguments, day
, month
, and
year
.
pub fn main() {
let day = 11
let month = October
let year = 1998
date(year: year, month: month, day: day)
}
It’s relatively common in Gleam programs to have this repetition of a label and a variable with the same name. The new label shorthand means that the variable name can be omitted if it matches the name of the variable to be supplied. With this the above would be written like so:
pub fn main() {
let day = 11
let month = October
let year = 1998
date(year:, month:, day:)
}
The shorthand can be used for labelled record fields and in pattern matching too.
pub fn get_year(date: Date) -> Year {
let Date(year:, ..) = date
year
}
Label shorthand code action
There is also a new language server code-action (an automated code edit you can trigger in your editor) to convert to the shorthand syntax.
// Before
case date {
Day(day: day, month: month, year: year) -> todo
}
// After
case date {
Day(day:, month:, year:) -> todo
}
Thank you Giacomo Cavalieri for these features!
Adding labels action
The second code action in this release is one to automatically add the labels that a call accepts.
// Before
pub fn main() {
Date()
}
// After
pub fn main() {
Date(year: todo, month: todo, day: todo)
}
And now the programmer can replace the todo
expressions with whatever values
are appropriate, and they didn’t have to refer to the documentation to remember
what the labels are.
Thanks Giacomo Cavalieri once again!
Label access completion
And lastly on the label front, Ameen Radwan has added support for completion of labelled record fields.
Type a dot (.
) after a record and the language server will suggest the fields
you can access on the record, along with their types. Labels will also be
suggested when when writing a function call or record construction that has
labels.
Completions are now sorted by priority based on why the completion is in the list. This means that more specific completions like labels and local definitions will be shown before more broad completions like functions from a not yet imported module.
Thank you Ameen!
Signature help
The Gleam language server now implemented signature help. This means that when you’re calling a function your editor will display the documentation for the function as well as highlight which argument you need to supply next.
A picture is worth a thousand words, so presumably a video is a small book. Here’s a demonstration:
Thank you Giacomo Cavalieri for this!
Unmistakable warnings
The Gleam build tool implements incremental compilation, so a module will only be recompiled if its definition changes. This means that Gleam compile times stay low even as codebases grow very large.
One problem with the implementation was that if a module emitted a warning
during compilation it would not be printed during future compilation unless
the module was edited, as it would be cached instead. This could result in
people not realising that their project has warnings as nothing was displayed
when they run gleam build
or gleam test
.
Warnings are now emitted each time the project is built, ensuring that this mistake can no longer happen.
And on the topic of warnings, Damir Vandic has improved our Erlang typespec generation to silence new warnings that were added to Erlang in version OTP27. Thank you!
Targeted documentation
gleam docs build
now takes an optional --target
flag to specify the target
platform for the generated documentation. This typically is not needed but if
you use the discouraged conditional compilation features then it may be useful
for your project. Thank you Jiangda Wang!
Even more fault tolerance!
Gleam’s compiler implements fault tolerant analysis. This means that when there is some error in the code that means it is invalid and cannot be compiled, the compiler can still continue to analyse the code to the best of its ability, ignoring the invalid parts. Because of this Gleam language server can have a good understanding of the code and provide IDE feature even when the codebase is in an invalid state.
Our language server magician Ameen Radwan has continued to improve this capability and now the compiler retains more information in the presence of record accessor or function call related errors, giving you a better experience in your text editor.
Help for a common type definition mistake
This is Gleam’s syntax for defining a type named User
that has a single
constructor also named User
:
pub type User {
User(name: String)
}
This syntax is similar to the class syntax in some object oriented languages where you define the class and constructors for the class for it within it.
One common mistake is to try and use a C-style struct definition syntax in Gleam, but this syntax is invalid.
pub type User {
name: String
}
If you do this then the compile will now emit a custom error that show you what the correct syntax is and how to fix the problem:
error: Syntax error
┌─ /src/parse/error.gleam:3:5
│
3 │ name: String,
│ ^^^^ I was not expecting this
Each custom type variant must have a constructor:
pub type User {
User(
name: String,
)
}
Thank you Rahul D. Ghosal for this feature!
A similar improved error message is emitted for when trying to use a function in a guard expression, while due to its Erlang heritage only a constant-time subset of pure expressions are permitted in guards. Thank you Thomas!
Constant concatenation
The <>
string concatenation operator can now be used in constant expressions.
pub const greeting = "Hello"
pub const name = "Joe"
pub const sentence = greeting <> " " <> name <> "!"
Thank you again Thomas!
More JavaScript bit array support
Gleam has a literal syntax for constructing and pattern matching on bit arrays, providing a convenient and easier to understand alternative using bitwise operations, as is common in other languages. Currently not all options supported on the Erlang target are supported on the JavaScript target.
In this release Richard Viney has added
support for the little
and big
endianness options, the signed
and
unsigned
int options, 32-bit and 64-bit sized float options, and utf8
option. Thank you Richard!
Document symbols
The language server now supports listing document symbols, such as functions and constants, for the current Gleam file. You may use this in your editor to help you get a high-level overview of a module, or to help you navigate around a large file. This was added by PgBiel, thank you!
Case correction
Gleam uses snake_case
for variables and functions, and PascalCase
for types
and record constructors. Using a different case is a compile error, so you’ll
never have an argument about which case to use in Gleam!
In the event you accidentally use the wrong one the language server now suggests a code a action to automatically adjust the case to be correct.
// Before
let myNumber = 10
// After
let my_number = 10
Thank you Surya Rose for this feature!
Assert to case
The final code action, also from Surya Rose
is one to convert a let assert
expression into a semantically equivalent
case
and panic
expression.
// Before
let assert Ok(value) = get_result()
// After
let value = case get_result() {
Ok(value) -> value
_ -> panic
}
Thank you Surya!
And the rest
An extra special shout out to the bug hunters Ameen Radwan, Connor Szczepaniak, Giacomo Cavalieri, Juraj Petráš, PgBiel, sobolevn, and Surya Rose! You stars!
If you’d like to see all the changes for this release, including all the bug fixes, check out the changelog in the git repository.
A call for support
Gleam has no corporate backing and is entirely supported by individuals, most of which contributing between $5 and $20 USD per month. I am fantastically grateful for your support, thank you so much.
I currently earn 32% the median salary tech lead salary for the UK, substantially less than I earned before I dedicated all my time to Gleam.
If you appreciate Gleam, please support the project on GitHub Sponsors with any amount you comfortably can.
- 00bpa
- Aaron Gunderson
- Abdulrhman Alkhodiry
- ad-ops
- Adam Brodzinski
- Adam Johnston
- Adi Iyengar
- Adi Salimgereyev
- Adrian Mouat
- Ahmad El-Bobou
- Ajit Krishna
- Alembic
- Alex
- Alex Houseago
- Alex Manning
- Alex Viscreanu
- Alexander Koutmos
- Alexander Stensrud
- Alexandre Del Vecchio
- Ameen Radwan
- AndreHogberg
- andrew
- András B Nagy
- Andy Aylward
- Anthony Khong
- Anthony Maxwell
- Anthony Scotti
- António Dias
- Arnaud Berthomier
- Arthur Weagel
- Austin Daily
- Barry Moore
- Bartek Górny
- Ben Martin
- Ben Marx
- Ben Myles
- Benjamin Peinhardt
- Benjamin Thomas
- Benjamin Wireman
- bgw
- Bill Nunney
- brettkolodny
- Brian Dawn
- Brian Glusman
- Bruno Michel
- bucsi
- Carlo Gilmar
- Carlo Munguia
- Carlos Saltos
- Chad Selph
- Charlie Govea
- Chaz Watkins
- Chew Choon Keat
- Chris
- Chris Donnelly
- Chris King
- Chris Lloyd
- Chris Ohk
- Chris Rybicki
- Christopher Dieringer
- Christopher Keele
- clangley
- Cleo
- CodeCrafters
- Coder
- Cole Lawrence
- Colin
- Comamoca
- Connor Szczepaniak
- custompro98
- Daigo Shitara
- Dan Dresselhaus
- Daniel
- Danny Arnold
- Danny Martini
- Darshak Parikh
- Dave Lucia
- David Bernheisel
- David Sancho
- Denis
- Dennis Dang
- dennistruemper
- DeviousStoat
- Dillon Mulroy
- Dima Utkin
- Dmitry Poroh
- ds2600
- ducdetronquito
- dvic
- Edon Gashi
- Eileen Noonan
- eli
- Elliott Pogue
- Emma
- EMR Technical Solutions
- Erik Terpstra
- erikareads
- ErikML
- Ernesto Malave
- Étienne Lévesque
- Evaldo Bratti
- Evan Johnson
- Felix Mayer
- Fernando Farias
- Filip Figiel
- Fionn Langhans
- Florian Kraft
- Frank Wang
- G-J van Rooyen
- GearsDatapacks
- Georg H. Ekeberg
- Giacomo Cavalieri
- Graeme Coupar
- graphiteisaac
- grotto
- Guilherme de Maio
- Guillaume Hivert
- Hamir Mahal
- Hammad Javed
- Hampus Kraft
- Hanna
- Hannes Nevalainen
- Hannes Schnaitter
- Hayes Hundman
- Hayleigh Thompson
- Hazel Bachrach
- Henning Dahlheim
- Henry Firth
- Henry Warren
- Hex
- Hudson C. Dalpra
- human154
- Humberto Piaia
- Iain H
- Ian González
- Ian M. Jones
- Igor Goryachev
- Igor Montagner
- Igor Rumiha
- inoas
- Isaac Harris-Holt
- Ismael Abreu
- Ivar Vong
- J. Rinaldi
- Jacob Lamb
- Jake Barszcz
- James Birtles
- James MacAulay
- Jan Skriver Sørensen
- Jean-Luc Geering
- Jen Stehlik
- Jenkin Schibel
- Jeremy Jacob
- jiangplus
- Jimpjorps™
- Joey Kilpatrick
- Johan Strand
- John Björk
- John Gallagher
- John Pavlick
- John Thile
- Jonas Hedman Engström
- Jordy Kafwe
- Jorge Martí Marín
- Josef Richter
- Joseph Lozano
- Joshua Steele
- Julian Lukwata
- Julian Schurhammer
- Juraj Petráš
- Justin Lubin
- Justyn Hunter
- kaiwu
- Kero van Gelder
- Kevin Schweikert
- Kieran Gill
- kodumbeats
- Kramer Hampton
- Kryštof Řezáč
- Krzysztof G.
- Leandro Ostera
- Leon Qadirie
- Leonardo Donelli
- lidashuang
- LighghtEeloo
- Lily Rose
- Louis GUICHARD
- Loïc Tosser
- Lucas Pellegrinelli
- Lucian Petic
- Lukas Meihsner
- Luna
- Manuel Rubio
- Maor Kadosh
- Marcus André
- Marcøs
- Mariano Uvalle
- Marius Iversen
- Marius Kalvø
- Mark Holmes
- Mark Markaryan
- Mark Spink
- Marko Mušnjak
- Markéta Lisová
- Martin Janiczek
- Martin Rechsteiner
- martonkaufmann
- Matt Champagne
- Matt Robinson
- Matt Savoia
- Matt Van Horn
- Matthias Benkort
- Max McDonnell
- max-tern
- Michael Duffy
- Michael Jones
- Michael Kieran O’Reilly
- Michael Kumm
- Michael Mazurczak
- Michael Peng
- Michał Hodur
- Mike
- Mike Nyola
- Mike Roach
- Mikey J
- MiniApple
- MoeDev
- MzRyuKa
- Måns Östman
- n8n - Workflow Automation
- Natanael Sirqueira
- Nathaniel Knight
- NFIBrokerage
- Nick Chapman
- Nick Reynolds
- Nick Wilson
- Nicklas Sindlev Andersen
- Ninaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- NineFX
- Nomio
- Ocean
- OldhamMade
- optizio
- Osman Cea
- Patrick Wheeler
- Patrik Kühl
- Paul Gideon Dann
- Paul Guse
- Paulo Vidal
- Pawel Biernacki
- Pete Jodo
- Peter Rice
- Peter Saxton
- Petri-Johan Last
- PgBiel
- Philip Giuliani
- Pierrot
- Piotr Szlachciak
- Praveen Perera
- qingliangcn
- Race Williams
- Rahul Butani
- Rahul Ghosal
- Raúl Chouza
- Redmar Kerkhoff
- Reilly Tucker Siemens
- Renovator
- Richard Viney
- Rico Leuthold
- Ripta Pasay
- Rob
- Robert Attard
- Robert Ellen
- Robert Malko
- Rodrigo Heinzen de Moraes
- Ross Bratton
- Ruslan Ustitc
- Sam Aaron
- sambit
- Sammy Isseyegh
- Samu Kumpulainen
- Santi Lertsumran
- Savva
- Saša Jurić
- Scott Trinh
- Scott Wey
- Sean Jensen-Grey
- Sebastian Porto
- sekun
- Seve Salazar
- Shane Poppleton
- Shuqian Hon
- Simon Lydell
- Simone Vittori
- Stephen Belanger
- Steve Powers
- Strandinator
- syhner
- Sławomir Ehlert
- Theo Harris
- Thomas
- Thomas Ernst
- Thomas Teixeira
- Tim Brown
- Timo Sulg
- Tom Schuster
- Tomasz Kowal
- tommaisey
- Tristan de Cacqueray
- Tristan Sloughter
- Vassiliy Kuzenkov
- Vic Valenzuela
- Victor Rodrigues
- Vincent Costa
- Viv Verner
- Volker Rabe
- Volker Schlecht
- Weizheng Liu
- Wesley Moore
- William McKIE
- Willyboar
- Wilson Silva
- xhh
- Yamen Sader
- Yasuo Higano
- yoshi~
- Zhomart Mukhamejanov
- Zsombor Gasparin
- ~1847917
Thanks for reading, I hope you have fun with Gleam! 💜