Merry Christmas! Following in the Ruby tradition we’re having a release on Christmas day, and so Gleam v0.6 is here!

This release has one big change to how we define data structures in Gleam. To understand it lets take a look at how structs and enums have worked up until this point.

struct Cat {
  name: String
  age: Int
}

Structs are collections of named values. Under the hood they are represented as Erlang tuples, so Cat("Nubi", 2) would be {<<"Nubi">>, 2} in Erlang.

enum SchoolPerson {
  Teacher(String, Subject)
  Student(String)
}

Enum are also collections of values, only this time the values are not named. One way in which enums are more capable than structs is that they can have more than one constructor, so for example a SchoolPerson enum type can be either a Teacher or a Student.

Like structs enums are tuples at runtime, only they have their constructor name as the first element to help distinguish them, so Student("Louis") would be {student, <<"Louis">>} in Erlang. This atom tag makes enums compatible with Erlang records, allowing easier use within projects written in Erlang or Elixir.

So the differences between structs and enums were:

  1. Struct fields can have names.
  2. Enums are Erlang record compatible.
  3. Enums can have more than one constructor.

In v0.5 things changed a little.

It turned out that being able to label fields so they have names was useful, so enums gained labelled arguments (as did functions).

It turns out that being Erlang record compatible with a tag atom was useful for Erlang interop and for runtime debugging, so structs got this too.

At which point the only difference between enums and structs are the number of constructors, and there’s nothing stopping someone from defining an enum with a single constructor.

Structs became a subset of enums, so why have both?

Custom types

With v0.6 rather than structs and enums we have custom types. Here’s how the two examples above would be written using the new syntax:

type Cat {
  Cat(name: String, age: Int)
}

Cat is a custom type has a single constructor called Cat.

type SchoolPerson {
  Teacher(name: String, class: Subject)
  Student(name: String)
}

SchoolPerson is a custom type has a Teacher constructor and a Student constructor.

let louis = Student(name: "Louis")

In keeping with Erlang and Elixir an instance of one of these custom types is called a record. The variable louis is a Student record, and it has the type SchoolPerson.

This change makes the languages simpler (both to the user and within the compiler), and hopefully it’ll make Gleam a little easier to learn too. :)

Tuples

After this change struct is no longer a keyword, and it doesn’t make much sense to have a concept of anonymous structs without named structs, so anonymous structs have been renamed tuples.

let pair = tuple(1, "two")

The rest

There’s been a number a smattering of bug fixes in this release, see the changelog for further details.

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

Want to view some existing Gleam projects? Head on over to the awesome-gleam list. Looking for something to build in Gleam? Check out the suggestions tracker.

Thanks

Lastly, a huge thank you to the contributors to and sponsors of Gleam since last release!

If you would like to help make strongly typed programming on the Erlang virtual machine a production-ready reality please consider sponsoring Gleam via the GitHub Sponsors program.

Thank you! And have a fantastic new year! 💜