Gleam is a type safe and scalable language for the Erlang virtual machine, and today v0.15.0 has been released! Let’s take a look at some of the highlights.

More concise tuples

A common bugbear of Gleam developers so far has been that the tuple literal syntax is rather verbose.

pub fn main() -> tuple(Int, Float, String) {
  tuple(1, 2.0, "three")

After a good deal of discussion on GitHub and on Discord we settled on this new syntax inspired by the ECMAScript TC39 proposal and the tuple syntax of popular programming languages such as Python, Rust, and Haskell.

pub fn main() -> #(Int, Float, String) {
  #(1, 2.0, "three")

The Gleam compiler will continue to accept both syntaxes for now, with the tuple(..) syntax being removed at a later date. To automatically upgrade your code to the new syntax run gleam format within your project.

Thank you to Sebastian Porto for kicking off the discussion and suggesting the new syntax, Marcin Puc for implementing the new syntax, and everyone who contributed to the discussion.

Importable prelude module

Gleam’s prelude is where the core data types of Gleam are defined, such as Int, Result, and String. The contents of the prelude were automatically imported into every module, and there was no way to import them a second time.

This proved a problem in situations where a module defines a new type or value constructor with the same name as one of the items from the prelude, as it would no longer be possible to refer to the prelude one.

pub type TuringBool {
  True  // Bool's True being shadowed
  False // Bool's False being shadowed

pub fn does_it_halt(program) -> TuringBool {

pub fn is_problem_solvable() -> Bool {
  False // Wrong bool type!

Now with v0.15.0 the prelude module can be imported using the name gleam, enabling qualified use of prelude items.

import gleam

// ...

pub fn problem_is_solvable() -> Bool {
  gleam.False // Use the prelude False

Making assignments expressions

Assignments in Gleam are now expressions that return the value being assigned. Previously in Gleam assignments were statements, meaning they did not evaluate to anything and could not be the final form in a function or a block. This had two main drawbacks.

The first is an development ergonomics issue. When writing Gleam code it is often desirable to save as often as possible so that the type checker can inform you of any mistakes or inconsistencies in the code that has just been written.

pub fn main() {
  let x = run(1, 2, 3)
  // And now I've hit save...

If I write the code above and hit save I might expect the Gleam compiler to tell me whether I’ve used the run function correctly. Instead it would complain of a syntax error, leaving me none the wiser as to whether my code is correct until I add a placeholder value on the next line and hit save again. With this latest version of Gleam this code will now be accepted and type checked.

This is a minor change but it removes friction from the development workflow for users with these editing habits, making Gleam friendlier and easier to pick up. Developer experience is a first class concern of Gleam, Gleam should be as productive and enjoyable to write as possible.

The next issue is that previously it was not possible to have an assertion as the final form in a function or block, forcing the user to add a superfluous dummy value to be returned.

/// A function that asserts `segments` is non-empty and
/// starts with a slash.
pub fn assert_valid(segments) {
  assert ["/", ..] = segments

Typically we prefer to use the Result type to safely handle invalid states, but in some scenarios it is beneficial to take advantage of the Erlang virtual machine’s offensive programming and fault tolerance capabilities by using assertions like this. For example, when prototyping or writing background batch processing script.

Standard library additions

This release contains a lot of new standard library functions, mostly in the list and iterator modules.

Lists are Gleam’s primary ordered collection type. These new functions have been added for working with lists:

Iterators are similar to lists, except they are lazily evaluated. This makes them especially useful for processing dataset too large to load into memory at once. or to decreasing latency as the start of a collection can be processed before the rest has loaded.

Thank you to Marcin Puc, Sebastian Porto, Robert Attard, and evuez for all their work on the standard library this release.

Speeding up Gleam development

I am very happy to announce that I am returning to full time Gleam development! You can expect features and releases to be larger and more frequent over the coming year, and I cannot wait to share with you what we’ve got coming next! This is an exciting time for Gleam.

Gleam sponsorship is now my primary source of income. 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! ⭐

Try it out

If you want to try out the new version of Gleam head over to the getting started page. I’d love to hear how you find it and get your feedback so Gleam can continue to improve.

For all the details of this release check out the changelog files:

Thank you

Gleam is made possible by the support of all the people who have sponsored and contributed to the project, so a huge thank you to them. Thank you!

Thanks for reading! Have fun! 💜