Published 12 Jan, 2022 by Louis Pilfold
Gleam is a type safe and scalable language for the Erlang virtual machine (and JavaScript). Today Gleam v0.19.0 has been released, let’s take a look at what’s been added over the last month.
JavaScript support in the build tool
In the v0.18 we released the first version of the Gleam build tool, bringing a high quality and modern developer experience to Gleam projects. With v0.19 the build tool has been expanded to support Gleam’s JavaScript backend as well as the primary Erlang backend.
To instruct the build tool to compile to JavaScript add the target
entry to
your gleam.toml
.
name = "my_project"
version = "1.0.0"
target = "javascript" # Compile to JavaScript
[dependencies]
gleam_stdlib = "~> 0.19"
If your project is a library that supports both the Erlang and the JavaScript
targets then you may want to select between them on a case by case basis. To
support this workflow the optional --target
flag has been added to some of the
main gleam
commands such as gleam run
and gleam test
.
# Run the app on JavaScript
gleam run --target javascript
# Run the tests on Erlang
gleam test --target erlang
# Use the target specified in gleam.toml
gleam run
Erlang package precompilation
Gleam is part of the wider BEAM ecosystem. We benefit greatly from the other languages such as Erlang and Elixir, and we want to give back to those languages so they can benefit from Gleam too. Gleam is designed to be easy to use from other BEAM languages. There’s no overhead compared to calling regular Erlang code, and the generated APIs are idiomatic Erlang.
Any Gleam packages published to Hex (the BEAM ecosystem package manager) now includes the project code compiled to Erlang. Once the various build tools of the other languages have been updated they will be able to depend on packages written in Gleam without having the Gleam compiler installed.
We want to fit into the wider ecosystem so smoothly that Erlang and Elixir programmers might not even know they’re using Gleam at all! All they need to know is that the library they are using is rock-solid and doesn’t fail on them.
JSON in Gleam
Up until now if you want to use JSON in your Gleam program you’ll have imported one of the Erlang JSON libraries using Gleam’s FFI, but there’s been no official advice on which one to use or what the interface should be.
To resolve this the gleam_json
library has been released, which
provides fast, memory efficient, and type safe JSON encoding/decoding without
requiring any native code extensions.
Encoding JSON looks like this:
import myapp.{Cat}
import gleam/json.{object, string, array, int, null}
pub fn cat_to_json(cat: Cat) -> String {
object([
#("name", string(cat.name)),
#("lives", int(cat.lives)),
#("flaws", null()),
#("nicknames", array(cat.nicknames, of: string)),
])
|> json.to_string
}
And decoding JSON into a Gleam data type looks like this:
import myapp.{Cat}
import gleam/json.{DecodeError}
import gleam/dynamic.{field, list, int, string}
pub fn cat_from_json(json_string: String) -> Result(Cat, DecodeError) {
let cat_decoder = dynamic.decode3(
Cat,
field("name", of: string),
field("lives", of: int),
field("nicknames", of: list(string)),
)
json.decode(from: json_string, using: cat_decoder)
}
Both of these APIs are type safe and return informative error messages if given JSON that doesn’t conform to the expected format.
Faster JSON for all BEAM users
In researching which JSON backend to use for Gleam’s JSON library we discovered that the fastest and most memory efficient library was Michał Muskała’s Jason.
We wanted to use Jason, but unfortunately it was written in Elixir, which makes it difficult to use without going through the manual process of installing the Elixir compiler and standard library, as well as configuring your build tool to build it.
To resolve this issue we’ve converted Jason from Elixir to Erlang, so that it can be easily used in projects written in any BEAM language. In benchmarking it performs just as well as Jason, while also having a smaller compiled bytecode size.
This new Erlang version has been released as Thoas and is ready to be used in your Erlang projects, as well as being used as the backend for the Gleam JSON library.
An extra special thank you to Michał Muskała’s work in creating Jason. It’s a very impressive project and without it we would not have been able to make Gleam’s JSON library as good as it is.
A new decoder API
The above JSON decoding code snippet also shows off the new standard library API for safely decoding untyped data into well typed Gleam data. In short, it has been redesigned to be composable and more consise.
Here’s a decoder written using the old API.
import myapp.{Book}
import gleam/dynamic.{Dynamic, Decoder, typed_list, string, field}
pub fn book_decoder() -> Decoder(Book) {
fn(data: Dynamic) {
try title = field(data, "title")
try title = string(title)
try published = field(data, "published")
try published = int(published)
try authors = field(data, "authors")
try authors = typed_list(authors, string)
Ok(Book(title, published, authors))
}
}
And here it is with the new API.
import myapp.{Book}
import gleam/dynamic.{Decoder, list, string, field}
pub fn book_decoder() -> Decoder(Book) {
dynamic.decode3(
Book,
field("title", string),
field("published", int),
field("authors", list(of: string)),
)
}
I hope you’ll agree it’s much nicer to look at!
The errors returned when data has the incorrect format have also been improved.
With the new API errors are returned from all the problem fields (rather than
just the first one), and it includes a path
field which indicates where the
problem value could be found in the input data.
Gleam 💜 Elixir
Often people are interested in Gleam but are not ready to dive in and use it for everything. Understandable! Gleam is a young language. More often people would like to continue with their Elixir or Erlang project and some Gleam modules as it suits them.
To meet this need the mix_gleam
plugin for Elixir’s build tool
has been completely revamped. With it you can add Gleam code and Gleam
dependencies to your Mix project, and integrate with your usual Elixir workflow.
Huge thanks to Tynan Beatty for making this happen!
And the rest
Those are the big new things, but as always there’s lots of little improvements.
OTP applications from dependencies will be automatically started for you when using the Gleam build tool, removing one common source of confusion for people unfamiliar with Erlang/OTP.
The compile-package
API has been reworked, making it easier to use the Gleam
compiler from other build tools.
The source code formatter’s output format as been improved.
The compiler’s code generation tests have been converted to use snapshot testing, making it much faster and easier to make changes to the code generator. Thank you Michael Jones!
Checksums are now provided for precompiled Gleam binaries. Thank you Sam!
Lastly, some error messages have been improved and lots of bugs have been fixed.
How can I try it?
Instructions on how to install the latest version of Gleam can be found on the getting started page of the website. Once installed check out the language tour for an introduction to the language.
In addition to these changes this release also includes numerous other bug fixes and improvements. For all the details check out the changelog.
Supporting Gleam
If you would like to support me in making Gleam please consider sponsoring Gleam or asking your employer to sponsor Gleam. Every donation makes a difference, no matter how small, so thank you for your help.
And thank you!
Gleam is made possible by the support of all the people who have sponsored and contributed to the project. Thank you all!
- Adam Bowen
- Adam Brodzinski
- Adi Iyengar
- Alexander Koutmos
- Ali Farhadi
- Arnaud Berthomier
- Arno Dirlam
- Arto Bendiken
- Ben Marx
- Ben Myles
- Brian Glusman
- Bruno Michel
- Charles
- Chew Choon Keat
- Chris Lloyd
- Chris Young
- Christian Meunier
- clangley
- Clay
- Cole Lawrence
- Colin
- Cristine Guadelupe
- Damir Vandic
- Dan
- Dan Mueller
- Dave Lucia
- David Armstrong Lewis
- David Bernheisel
- David Flanagan
- Dennis Dang
- Drew Varner
- Edgar Gomes
- Edon Gashi
- Eric Meadows-Jönsson
- Erik Terpstra
- Florian Kraft
- Gitpod
- Guilherme de Maio
- Harshal
- Henry Warren
- Herdy Handoko
- human154
- Ian González
- Ingmar Gagen
- inoas
- Ivar Vong
- James MacAulay
- Jechol Lee (Trevor)
- Jeff Kreeftmeijer
- jiangplus
- Joe Corkerton
- John Doneth
- John Palgut
- Jonathan Arnett
- josh rotenberg
- José Valim
- Josías Alvarado
- João Veiga
- Kapp Technology
- kevin
- Kieran Gill
- Lars Lillo Ulvestad
- Lars Wikman
- Marcel Lanz
- Marcin Puc
- Marius Kalvø
- Mark Markaryan
- Markus
- Memo
- Michael Chris Lopez
- Michael Jones
- Michał Kowieski
- Michał Łępicki
- Michele Riva
- Mike Lapping
- Mike Roach
- Milton Mazzarri
- Nathaniel Knight
- Nick Reynolds
- Nicklas Sindlev Andersen
- NineFX
- OldhamMade
- Ole Michaelis
- Oliver Searle-Barnes
- Parker Selbert
- Pete Jodo
- porkbrain
- Praveen Perera
- qingliangcn
- Quinn Wilton
- Raúl Chouza
- Redmar Kerkhoff
- Reio Piller
- René Klačan
- Robert Attard
- Robin Mattheussen
- Sam Aaron
- Sam Pratt
- Sascha Wolf
- Saša Jurić
- Scott Wey
- Sean Jensen-Grey
- Sebastian Porto
- Shane Sveller
- Shunji Lin
- Shuqian Hon
- silicium14
- Simone Vittori
- SkunkWerks GmbH
- Strand Communications
- Terje Bakken
- Tim Buchwaldt
- Tobias Hermann
- Tom Calloway
- Tomasz Kowal
- Tomochika Hara
- Tristan Cacqueray
- Tristan Sloughter
- tynanbe
- Victor Borja
- Vincent Le Goff
- Vladimir Kuznetsov
- Wilson Silva
- Wojtek Mach
- YourMother-really
- Yt
- Yu Matsuzawa
Thanks for reading! Happy hacking! 💜