Published 09 Jul, 2024 by Louis Pilfold
Gleam is a type safe and scalable language for the Erlang virtual machine and JavaScript runtimes. Today Gleam v1.3.0 has been published, and we’re going to go over all that’s new.
Auto-imports
Excellent developer tooling is important for programmers to be productive so the Gleam core team develops and maintains the Gleam language server, which provides IDE features for all text editors. As the language only reached v1.0.0 a handful of months ago the language server is one of the least mature parts of the toolchain, but it is improving very rapidly!
With this release it will now suggest completions for values and types from any module in the project or its dependencies, and if the module hasn’t been imported yet then an import statement will be added for you.
For example, if you have this code:
pub fn main() {
[1, 2, 3] |> eac
}
And you accept list.each
as the completion for eac
, you’ll get this:
import gleam/list
pub fn main() {
[1, 2, 3] |> list.each
}
Thank you Ameen Radwan for this feature!
Tolerant expressions
The language server is fault tolerant, meaning it is able to work with and understand your code even when it has errors that would cause the compiler to halt. Without this feature the information and assistance offered in your editor would degrade when your project does not compile successfully, such as when performing a refactoring.
Fault tolerance was introduced in v1.2.0 and was at a module definition level granularity. Ameen Radwan has improved this to be expression level, giving further information in functions which have errors within them.
Completion improvements
The language server protocol has some ambiguities around completions, so if one of the completion APIs is used then you will get different results in different text editors. Resident language-server magician Ameen Radwan has upgraded the language server to use the more complex completion API which gives consistent results in all text editors.
On top of that completions are no longer provided inside comments, thank you Nicky Lim!
Import cycles diagnostics
The language server protocol has a way for servers to send messages to the client to be displayed to the user. However, one newer editor that is very popular with Gleam programmers doesn’t support this API yet, so any project errors sent this way wouldn’t be displayed to the programmer.
The most common errors which would cause this problem are the ones for import cycles, so Ameen Radwan has converted this error to be attached to the locations of all of the import statements which cause the cycle.
As part of this work the language server diagnostics system has been upgraded to make use of the protocol’s ability to have diagnostics nested within each other, a feature which can benefit more errors and warnings in future.
Helpful hidden hovering
Gleam has a syntax for ignoring record fields that you’re not interested in when pattern matching on them:
case pokemon {
Pokemon(name: "Staryu", ..) -> "Hi Staryu!"
Pokemon(name: name, ..) -> "Hello " <> name
}
Giacomo Cavalieri has made it so when you
hover over the ..
in your editor it’ll show you the details of the remaining
fields, so you can easily see what they are and add them to your pattern as
required.
Unused positional fields:
- `Int`
Unused labelled fields:
- `sprite: String`
- `abilities: List(String)`
- `types: List(String)`
Redundant tuple code-action
Gleam v1.2.0 added a warning for when a redundant tuple is used to pattern match
on multiple values at the same time in a case
expression. The language server
now has a code-action that can fix the code with a single button press.
case #(a, b) {
#(1, 2) -> todo
_ -> todo
}
Becomes:
case a, b {
1, 2 -> todo
_, _ -> todo
}
Thank you Giacomo Cavalieri!
gleam add
, gleam remove
The Gleam command line has two commands for quickly adding and removing
dependencies without manually editing the gleam.toml
project file.
Thanks to Rahul D. Ghosal gleam add
can now take
an optional package version specifier:
gleam add lustre@1.2.3 # "1.2.3"
gleam add lustre@1.2 # ">= 1.2.0 and < 2.0.0"
gleam add lustre@1 # ">= 1.0.0 and < 2.0.0"
And gleam remove
will now present an error if a package being removed does not
exist as a dependency in the project. Previously it would see that package
already doesn’t exist and report the removal as successful.
Thank you Changfeng Lou for this!
Syntax warning and error improvements
Thanks to Giacomo Cavalieri the compiler now emits a warning for redundant function captures in a pipeline:
warning: Redundant function capture
┌─ /src/warning/wrn.gleam:5:17
│
5 │ 1 |> wibble(_, 2) |> wibble(2)
│ ^ You can safely remove this
This function capture is redundant since the value is already piped as the
first argument of this call.
See: https://tour.gleam.run/functions/pipelines/
And thanks to Antonio Iaccarino there is now a
more informative error explaining why the ..
list prepending syntax cannot be
used for appending.
error: Syntax error
┌─ /src/parse/error.gleam:4:14
│
4 │ [..rest, last] -> 1
│ ^^^^^^ I wasn't expecting elements after this
Lists are immutable and singly-linked, so to match on the end
of a list would require the whole list to be traversed. This
would be slow, so there is no built-in syntax for it. Pattern
match on the start of the list instead.
On the subject of the ..
syntax, using it without a comma ([a..b]
) has been
deprecated in favour of the recommended [a, ..b]
syntax.
This was to avoid it being mistaken for a range syntax, which Gleam does not have. The comma-less syntax being accepted by the parser was not intentional and was a mistake by the Gleam compiler developers. If a Gleam v2.0.0 is released in future then this mistake will be corrected then. Thank you Giacomo Cavalieri!
And lastly on the syntax side, Rahul D. Ghosal has improved the error message for an unexpected token to include more information. This change was prompted to help people understand what the issue was when trying to use a keyword as a variable name:
error: Syntax error
┌─ /src/parse/error.gleam:3:9
3 │ A(type: String)
│ ^^^^ I was not expecting this
Found the keyword `type`, expected one of:
- `)`
- a constructor argument name
OTP 27 keyword support
Erlang/OTP 27 introduced two new keywords to Erlang, maybe
and else
.
Jake Barszcz and Giacomo Cavalieri
have updated Gleam’s Erlang code generation to appropriately escape any
functions, types, and record constructors which would clash with the new Erlang
syntax.
JavaScript byte alignment errors
When compiling to JavaScript Gleam’s bit-arrays must contain a whole number of bytes. In future this limitation will be lifted, but today it is an error to attempt to construct one with some other number of bits.
The error for this has been moved from run-time to compile-time when a constant
number is used with the size
option of a bit-array.
error: Unsupported feature for compilation target
┌─ /src/test/gleam_test.gleam:6:5
│
6 │ <<1:size(5)>>
│ ^^^^^^^^^
Non byte aligned array is not supported for JavaScript compilation.
Thank you Pi-Cla for this improvement!
Arithmetic guards
The Erlang virtual machine only supports a limited subset of expressions in case clause guards, and Gleam inherits this restriction. With this version Gleam now supports arithmetic operations on floats and ints here too.
case numbers {
[x, y] if x + y == 0 -> "zero sum"
_ -> "something else"
}
Thank you Danielle Maywood for this!
Hints for JavaScript bundlers
When compiling Gleam to JavaScript it may be useful to use a JavaScript bundler such as esbuild or Vite to perform dead-code elimination and to combine all the modules into a single file.
These bundlers don’t know as much about the code as the Gleam compiler does, so
at times they have to be conservative with dead code elimination as they cannot
tell if code has side effects or not, and so cannot tell if removing some code
would change the behaviour of the program. To give them a little help Gleam will
output /* @__PURE__ */
annotation comments to pure constructors, which
bundlers will use to perform more aggressive elimination.
Thank you Giacomo Cavalieri!
And the rest
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.
Thanks
Gleam is made possible by the support of all the kind people and companies who have very generously sponsored or contributed to the project. Thank you all!
If you like Gleam consider sponsoring or asking your employer to sponsor Gleam development. I work full time on Gleam and your kind sponsorship is how I pay my bills!
Alternatively consider using our referral link for CodeCrafters, who have courses on implementing Redis, SQLite, and grep in Gleam. Use your training budget to learn and to support Gleam too!
- 00bpa
- Aaron Gunderson
- Abdulrhman Alkhodiry
- Ace
- ad-ops
- Adam Brodzinski
- Adam Johnston
- Adi Iyengar
- Adi Salimgereyev
- Ajit Krishna
- Akira Komamura
- Alembic
- Alex Manning
- Alex Viscreanu
- Alexander Koutmos
- Alexander Stensrud
- Alexandre Del Vecchio
- Alyx
- AndreHogberg
- András B Nagy
- Andy Aylward
- Anthony Khong
- Anthony Maxwell
- Anthony Scotti
- Antonio Iaccarino
- António Dias
- Arnaud Berthomier
- Arthur Weagel
- Austin Daily
- Barry Moore
- Bartek Górny
- Ben Martin
- Ben Marx
- Ben Myles
- Benjamin Peinhardt
- Benjamin Thomas
- bgw
- Bill Nunney
- Brad Bollenbach
- Brad Lewis
- brettkolodny
- Brian Dawn
- Brian Glusman
- Bruno Michel
- bucsi
- bwireman
- Carlo Munguia
- Carlos Saltos
- Carter Davis
- Chad Selph
- Changfeng Lou
- Charlie Govea
- Chaz Watkins
- Chetan Bhasin
- Chew Choon Keat
- Chris Donnelly
- Chris King
- Chris Lloyd
- Chris Ohk
- Chris Rybicki
- Christopher Dieringer
- Christopher Keele
- clangley
- Cleo
- CodeCrafters
- Coder
- Cole Lawrence
- Colin
- Collin
- Comamoca
- Constantine Manakov
- Cristine Guadelupe
- Daigo Shitara
- Damir Vandic
- Dan Dresselhaus
- Daniel
- Danielle Maywood
- Danny Arnold
- Danny Martini
- Darshak Parikh
- Dave Lucia
- David Bernheisel
- David Sancho
- Day Fisher
- Denis
- Dennis Dang
- dennistruemper
- Dillon Mulroy
- Dima Utkin
- Diogo Korok
- Dmitry Poroh
- ds2600
- ducdetronquito
- Edon Gashi
- Eileen Noonan
- eli
- Elliott Pogue
- Emma
- EMR Technical Solutions
- Erik Lilja
- Erik Terpstra
- erikareads
- ErikML
- Ernesto Malave
- Felix Mayer
- Fernando Farias
- Filip Figiel
- Fionn Langhans
- Florian Kraft
- frozen
- GearsDatapacks
- Georg H. Ekeberg
- Giacomo Cavalieri
- Gioele Bucci
- Graeme Coupar
- grotto
- Guilherme de Maio
- Guillaume Hivert
- Hammad Javed
- Hampus Kraft
- Hannes Schnaitter
- Hayes Hundman
- Hayleigh Thompson
- Hazel Bachrach
- Henning Dahlheim
- Henry Firth
- Henry Warren
- Hex
- human154
- Humberto Piaia
- Iain H
- Ian González
- Ian M. Jones
- Igor Goryachev
- Igor Montagner
- Igor Rumiha
- inoas
- Isaac
- 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™
- jmcharter
- Joey Kilpatrick
- Johan Strand
- Johannes
- John Björk
- John Gallagher
- John Pavlick
- John Strunk
- John Thile
- Jonas Hedman Engström
- Jonathan Arnett
- Josef Richter
- Joshua Hall
- Joshua Steele
- Julia Pitts
- Julian Kalema Lukwata
- Julian Lukwata
- Julian Schurhammer
- Juraj Petráš
- Kero van Gelder
- Kevin Schweikert
- Kieran Gill
- kodumbeats
- Komo
- Kramer Hampton
- Kryštof Řezáč
- Krzysztof G.
- Leandro Ostera
- Leon Qadirie
- Leonardo Donelli
- lidashuang
- LighghtEeloo
- Lily Rose
- Loïc Tosser
- Lucas Pellegrinelli
- Lucian Petic
- Luna
- Mads Hougesen
- Manuel Rubio
- Marcus André
- Marcøs
- Mariano Uvalle
- Marius Kalvø
- Mark Holmes
- Mark Markaryan
- Marshall Bowers
- Martin Janiczek
- Martin Rechsteiner
- Mathieu Darse
- Matias Kinnunen
- Matt Champagne
- Matt Savoia
- Matt Van Horn
- Matthew Scharley
- Matthias Benkort
- Max McDonnell
- max-tern
- miampf
- Michael Duffy
- Michael Jones
- Michael Kieran O’Reilly
- Michael Kumm
- Michael Mark
- mihaimiuta
- Mike
- Mike Nyola
- Mike Roach
- Mikey J
- MoeDev
- MzRyuKa
- Måns Östman
- n8n - Workflow Automation
- Natanael Sirqueira
- Nathaniel Knight
- ncihnegn
- NFIBrokerage
- Nick Chapman
- Nick Reynolds
- Nicklas Sindlev Andersen
- Nicky Lim
- Ninaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- NineFX
- Nomio
- Ocean Armstrong Lewis
- Ofek Doitch
- OldhamMade
- Oli Clive-Griffin
- Oliver Linnarsson
- Om Prakaash
- optizio
- Osman Cea
- Patrick Wheeler
- Patrik Kühl
- Paul Gideon Dann
- Paul Guse
- Pawel Biernacki
- Pete Jodo
- Peter Rice
- Peter Saxton
- Philip Giuliani
- Pi-Cla
- Piotr Szlachciak
- Praveen Perera
- qingliangcn
- Qynn Schwaab
- Race Williams
- Rado
- Rahul Butani
- Rahul D. Ghosal
- Rahul Ghosal
- Ratio PBC
- Raúl Chouza
- Redmar Kerkhoff
- Reilly Tucker Siemens
- Renovator
- Richard Viney
- Rico Leuthold
- Ripta Pasay
- Robert Attard
- Robert Ellen
- Robert Malko
- Ross Bratton
- Ross Cousens
- Ruslan Ustits
- Ryan Moore
- Sam Aaron
- sambit
- Sami Fouad
- Sammy Isseyegh
- Samu Kumpulainen
- Santi Lertsumran
- Saphira Kai
- Savin Angel-Mario
- Saša Jurić
- Scott Trinh
- Scott Wey
- Sean Jensen-Grey
- Sebastian Porto
- sekun
- Seve Salazar
- Shane Poppleton
- Shuqian Hon
- Simon Curtis
- Simone Vittori
- Sonny Kjellberg
- Stephen Belanger
- syhner
- Szymon Wygnański
- Sławomir Ehlert
- TankorSmash
- Theo Harris
- Thomas
- Thomas Ernst
- thorhj
- 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
- Weizheng Liu
- Wesley Moore
- Willyboar
- Wilson Silva
- xhh
- xxKeefer
- Yamen Sader
- Yasuo Higano
- Zhomart Mukhamejanov
- Zsombor Gasparin
- ~1847917
Thanks for reading, I hope you have fun with Gleam! 💜