Gleam is a type-safe and scalable language for the Erlang virtual machine and JavaScript runtimes. Today Gleam v1.8.0 has been published. Let’s take a look!

Rename variables and arguments

The most desired feature for a long time has probably been “rename” in the language server. I’m happy to announce that the first iteration of this has been implemented! Local variables and function arguments can be renamed. For example, given this code:

pub fn main() {
  let wibble = 10
  wibble + 1
}

Triggering the “rename” command in your editor with your cursor on wibble and then entering my_number will cause the language server to edit your code like so:

pub fn main() {
  let my_number = 10
  my_number + 1
}

It’s not limited to variables that are used a single time, all the uses will be converted as required. This is just the first iteration of this feature, renaming for other things in Gleam code will come in future releases.

Thank you Surya Rose for this long awaited feature!

Erlang documentation integration

Erlang OTP27 added the -doc attribute, a new standard for adding documentation to Erlang based code. The documentation for functions with this attribute can be programmatically accessed, for example using the documentation helper in the Erlang and Elixir REPLs.

Eshell V15.1.3 (press Ctrl+G to abort, type help(). for help)
1> h(gleam@list, map).

  map(List, Fun)

  Returns a new list containing only the elements of the first list after the
  function has been applied to each one.

Examples

     map([2, 4, 6], fn(x) { x * 2 })
     // -> [4, 8, 12]

As you can see, Giacomo Cavalieri has added support for this attribute in the Gleam code generator, so Gleam documentation can be accessed like this from any BEAM language. The code is generated in such a fashion that it will continue to work with older version of Erlang/OTP also. Thank you Jak!

Generate function code action

The language server can now generate the definition of functions that do not yet exist. For example if I write the following piece of code:

import gleam/io

pub type Pokemon {
  Pokemon(pokedex_number: Int, name: String)
}

pub fn main() {
  io.println(to_string(pokemon))
}

Triggering the “generate function” code action on the to_string function call will cause the language server to edit the code to add the empty function definition, including type annotations.

fn to_string(pokemon: Pokemon) -> String {
  todo
}

Programmers who write this code “top down” will find this especially convenient. Thank you to Giacomo Cavalieri, a “top down” programmer who I’m pretty sure added this entirely for himself.

Pattern match code action

The language server now suggests a code action to pattern match on a variable. For example, if you have this code:

pub fn main() {
  let result = list.first(a_list)
}

Triggering the code action on the result variable will generate the following code for you:

pub fn main() {
  let result = list.first(a_list)
  case result {
    Ok(value) -> todo
    Error(value) -> todo
  }
}

This works with values of any type, adding all the patterns you would need to exhaustively pattern match on them. It also works for function arguments as well as variables. Thank you Giacomo Cavalieri!

More fault tolerant compilation

Fault tolerant compilation is what allows the language server to still help you work with your code even when it is in an invalid state, a feature which is vital for a good experience refactoring or fixing Gleam code.

Surya Rose and Giacomo Cavalieri have improved code analysis to make the compilation of body-less case expressions and function pipelines fault tolerant. This will be extra impactful for autocompletion while writing new code. Thank you both for this!

Result wrapping hints

Gleam uses a result type for error handling instead of exceptions. At times the programmer may forget to add the Ok or Error needed in fallible functions, so Giacomo Cavalieri has made the compiler suggest where to add these to solve a type mismatch.

pub fn greet_logged_user() {
  use <- bool.guard(when: !logged_in, return: Error(Nil))
  "Hello!"
}
error: Type mismatch
  ┌─ /main.gleam:7:3
  │
7 │   "Hello!"
  │   ^^^^^^^^ Did you mean to wrap this in an `Ok`?

Expected type:

    Result(a, Nil)

Found type:

    String

Thank you Jak!

gleam deps tree

Gleam uses the Hex, the package manager for the BEAM ecosystem. The build tool will automatically download and compile appropriate versions of the dependencies your project needs, along with their dependencies.

The new gleam deps tree command can be used to view the relationship between all your dependencies.

$ gleam deps tree

project_a v1.0.0
├── package_b v0.52.0
└── package_c v1.2.0
    └── package_b v0.52.0

The --package option can be used to view just a portion of the dependency tree.

$ gleam deps tree --package package_c

package_c v1.2.0
└── package_b v0.52.0

And the --invert option can be used to view all paths from a package to the root of the project, which can be very useful for understanding why a particular package version was included in the project.

$ gleam deps tree --invert package_b

package_b v0.52.0
├── package_c v1.2.0
│   └── project_a v1.0.0
└── project_a v1.0.0

Thank you Ramkarthik Krishnamurthy for this new command!

HTML documentation hotkeys

Gleam can generate HTML documentation for your code when you run gleam docs build, and it will automatically generate and publish this documentation to HexDocs when publishing a package.

Sambit Sahoo has added hotkeys, making the search input be focused when cmd/ctrl + k, s or / is pressed. Thank you!

Invalid project name correction

Gleam project names have to be all lowercase letters and underscores and numbers, and not collide with any Gleam keywords. The glean new command would reject invalid names, but now it will suggest a valid name instead and ask if the programmer would like to use that instead.

$ gleam new type
We were not able to create your project as `type` is a reserved word in
Gleam.

Would you like to name your project 'type_app' instead? [y/n]:

Thank you Diemo Gebhardt for this!

Better “fill labels” code action

The language server can now fill in the labels of any function call, even when only some of the arguments are provided. For example:

import gleam/string

pub fn main() {
  string.replace("wibble")
}

Will be completed to:

import gleam/string

pub fn main() {
  string.replace("wibble", each: todo, with: todo)
}

Thank you Giacomo Cavalieri!

And the rest

And thank you to the bug fixers and error message improvers: Giacomo Cavalieri, Jiangda Wang, John Strunk, Kasim, shayan, Surya Rose, and yoshi

For full details of the many fixes and improvements they’ve implemented see the changelog.

A call for support

Gleam is not owned by a corporation; instead it is entirely supported by sponsors, most of which contribute between $5 and $20 USD per month, and Gleam is my sole source of income.

We have made great progress towards our goal of being able to appropriately pay the core team members, but we still have further to go. Please consider supporting the project or Giacomo Cavalieri specifically on GitHub Sponsors.

Thank you to all our sponsors! And especially our top sponsor: Lambda.

Try Gleam

This release is dedicated to the memory of my grandfather, Len Pilfold, who passed away in January.