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!

Thanks for reading, I hope you have fun with Gleam! 💜

Try Gleam