Published 03 Apr, 2023 by Louis Pilfold
Gleam is a type safe and scalable language for the Erlang virtual machine and JavaScript runtimes. Today Gleam v0.28.0 has been released, let’s take a look at what’s new.
Language server revamp
Gleam is all about productivity and making the job of the programmer as low-stress as possible. To be productive we need more than just a great language, we also need great tooling around that language, including top-notch editor support. To this end the Gleam binary includes a language server, a headless IDE engine that adds Gleam functionality to VSCode, Vim, Emacs, Helix, and any other editor that supports the protocol.
The Gleam language server was released in Gleam v0.21.0, and while a popular addition it was rather limited in this initial version. In the releases since then much work has been done restructuring compiler internals to make further improvements to the language server possible. With this release the first batch of those improvements are ready for use.
Lightning fast analysis
The Gleam compiler is very fast, so the build tool could afford to be a little naive and recompile an entire package when a single file changed, rather than having fine-grained incremental compilation. This became a problem when the language server was introduced because rebuilding a package was more work than we wanted to perform on every keystroke, so the package would only be rebuilt when the user saved their changes, meaning the programmer would only have up-to-date information in their editor after saving.
With Gleam v0.26.0 the build tool learnt how to perform per-module incremental compilation, and with this release the language server now uses that to parse and analyse code on every keystroke. Gleam is now among the snappiest and most responsive language servers I’ve used!
Thank you John Björk for your work on this feature!
There’s still lots of things we can do to improve the performance of the compiler and build tool, we’re only going to get faster from here on out.
Monorepo support
Gleam is most commonly run using the Erlang virtual machine, but it can also be compiled to JavaScript and run in other places, such as web browsers. Folks in the Gleam community use this to build web applications where both the frontend and backend are written in Gleam, with both parts living in the same code repository.
louis ~/src/gleam/developer-survey $ tree -L 2
.
├── Dockerfile
├── README.md
├── fly.toml
├── backend
│ ├── gleam.toml
│ ├── manifest.toml
│ ├── src
│ └── test
└── frontend
├── gleam.toml
├── manifest.toml
├── src
└── test
Previously the language server only suppored a single Gleam project per editor instance, with the editor open at the root. If another Gleam project was opened the language server would not be able to analyse it, offering very little assistance to the programmer.
Gleam can now handle as many Gleam projects as you’d like to open in a single editor session, and they can be nested in any way you like. The language server will spin up a new engine for each project opened, and route requests to the correct one per-file.
More on-hover information
Access to good documentation is vital, so the language server will now show documentation when you hover over Gleam code in your editor.
Previously information was only shown on hover for values, but now pattern-match patterns are also supported, showing their type and their documentation.
And that’s all the user-facing changes to the language server in this release. Let’s take a look at the other changes.
Checksum based caching
Gleam gained per-module incremental compilation in v0.26.0, based off of the file modification time. One drawback with this approach is that it will consider a module to need recompiling if the file modification time changes, even if the contents of the file have not changed, for example when changing git branches.
The build tool now checks the checksum of the file contents after checking the modification time, and only recompiles the module if both have changed, reducing the amount of unnecessary work.
Thank you Nikita Lapkov for this feature!
Unary negation
Gleam now has a unary negation operator, -
, which can be used to negate
integers, while before only integer literals could be negated with -
.
pub fn negate(x: Int) -> Int {
-x
}
A little funny that we’ve got this far without this feature, but there you go! Thank you Zack for this feature!
Syntax refinements
In Gleam let x = 1
is an expression and returns a value, and it could be used
anywhere that an expression can be used. This resulted in some questionable code
being supported, with potentially confusing scoping rules for variables defined.
let x = let y = 1
// Is y in scope here?
1 + let x = 1
// Is x in scope here?
To help keep Gleam easy to understand the syntax has been restricted slightly, with assignments only being permitted within functions and blocks.
let x = {
let y = 1
}
1 + {
let x = 1
}
This should make it clearer to the programmer where variables go out of scope.
On the subject of syntax, the deprecated assert
and try
syntaxes have been
removed, and semicolons have changed from being whitespace to being a syntax
error. If your code has any of these run the gleam fix
command with Gleam
v0.27.* and it will be auto-updated for you.
Running modules
The gleam run
command now supports running a module of your choice, rather
than just the main module for your project.
gleam run --module my/favourite/module
The module can also be from a dependency, opening up the door to dependency provided tooling being straight-forwardly usable from the command line. For example, a web application framework may provide a project scaffolding command to quickly get started with the framework.
gleam add magic_framework
gleam run -m magic_framework init
Thank you Lunarmagpie for this feature!
Fast immutable maps on JavaScript
In Gleam all data is immutable and very fast. Or at least, it is now! Up until this release the implementation of immutable maps in JavaScript has been slower than we would like it to be, some operations performing a full-copy of the map before updating it.
With this release we have a brand new and very fast persistent hash map implementation on JavaScript, inspired by Clojure’s hash map implementation.
Thank you to Julian Schurhammer for this very impressive and much appreciated contribution!
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!
- Aaron Gunderson
- Adam Brodzinski
- Adi Iyengar
- Alembic
- Alex Manning
- Alexander
- Alexander Koutmos
- Alexandre Del Vecchio
- Ali Farhadi
- Anthony Khong
- Anthony Scotti
- Arnaud Berthomier
- Ben Marx
- Ben Myles
- brettkolodny
- Brian Glusman
- Bruno Michel
- Carlo Gilmar
- Carlos Saltos
- Catalin Marincia
- Chew Choon Keat
- Chris Lloyd
- Chris Ohk
- Christopher Keele
- Chuck Daniels
- clangley
- Clay
- Cole Lawrence
- Colin
- Cora Grant
- Cosmo Shin (신의하)
- Cristine Guadelupe
- Damir Vandic
- Dan Dresselhaus
- Danielle Maywood
- Danny Martini
- Dave Lucia
- David Armstrong Lewis
- David Bernheisel
- David Flanagan
- Edon Gashi
- Elliott Pogue
- Erik Terpstra
- Ernesto Malave
- Ethan Pang
- Fabian
- Fernando Farias
- Filip Figiel
- Florian Kraft
- fly.io
- François Cardinaux
- Graeme Coupar
- Guilherme de Maio
- Gustavo Villa
- Harry Bairstow
- Hayleigh Thompson
- Henry Warren
- Hex
- Ingmar Gagen
- inoas
- Ivar Vong
- James MacAulay
- Jan Skriver Sørensen
- Jasper van Nieuwenhuizen
- Jen Stehlik
- jiangplus
- John Björk
- John Gallagher
- John Palgut
- Jonas Hedman Engström
- Jonathan Arnett
- Julian Schurhammer
- Justin Blake
- Kayla Washburn
- Kieran Gill
- Lars Wikman
- Leon Qadirie
- lidashuang
- Lunarmagpie
- Manuel Rubio
- Marcel Lanz
- Marcin Puc
- Marius Kalvø
- Mark Holmes
- Mark Markaryan
- Markus
- Martin Janiczek
- Mathias Jean Johansen
- Matt Van Horn
- Matthias Benkort
- Max Lee
- max-tern
- Michael Chris Lopez
- Michael Davis
- Michael Jones
- Michael Kumm
- Mike Roach
- Nathaniel Knight
- Nick Reynolds
- Nicklas Sindlev Andersen
- Nikita Lapkov
- NineFX
- Noah Betzen
- noam sauer-utley
- OldhamMade
- Ole Michaelis
- ontofractal
- Parker Selbert
- Paul Gideon Dann
- Pete Jodo
- porkbrain
- Praveen Perera
- qingliangcn
- Raúl Chouza
- Redmar Kerkhoff
- Rico Leuthold
- Robert Attard
- Robert Ellen
- Rocky Neurock
- Ryan Winchester
- Sam Aaron
- Sammy Isseyegh
- Sascha Wolf
- Saša Jurić
- Scott Wey
- Sean Jensen-Grey
- Sebastian Porto
- Seve Salazar
- shayan javani
- Signal Insights
- Simon Sommer
- Simone Vittori
- Stefan Luptak
- Steven Joseph
- Strand Communications
- Szymon Wygnański
- Terje Bakken
- Theo Harris
- Tomasz Kowal
- Tristan de Cacqueray
- Tristan Sloughter
- Uku Taht
- VlkrS
- Weizheng Liu
- Wilson Silva
- Wojtek Mach
- Yorick Peterse
- Yu Matsuzawa
- Zack H
- Zsombor Gasparin
Thanks for reading! Happy hacking! 💜