Gleam v0.19 released!

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.

⭐ Or alternatively give us a star on GitHub! ⭐

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!

Thanks for reading! Happy hacking! 💜