Fun with Gleam

This’ll be a short blog post, but Gleam (v0.25.0) is an Erlang OTP language, akin to Elixir (in fact, recently added full compatibility with Elixir packages). It’s been fun so far.

I think the error messages are great and the functional style language is a lot of fun to wrap my brain around. I have had some clerical issues trying to find resources for things as simple as opening files and referencing type variants, but the discord channel has been really helpful.

For reference, opening files is apparently done through an Erlang bridge. First add gleam_erlang to your project:

$ gleam add gleam_erlang

Then use it like so:

import gleam/erlang/file

pub fn main() {
  file.read("./input/two.txt")
}

Thanks to Mark Holmes for assisting me on the Gleam Discord with that tip!

And referencing type constructors, or what look suspiciously like Rust’s Enum variants, after import can be confusing.

If you have a custom type like so:

// src/animal.gleam

// 👇 this is a "type"
pub type Move {
  // 👇 these are "type constructors"
  Rock
  Paper         
  Scissors
}

And I was trying to reference it elsewhere like this:

import move.{Move}

pub fn main() {
  move.compare(Move.Rock, Move.Paper)
}

You will get an error. That is because types and type constructors both importable at the same level. So you *can* import Move as the umbrella type for Rock, Paper, and Scissors, but if you’re just going to use Rock and Paper, then you can do so like this:

import move.{Rock, Paper}

pub fn main() {
  move.compare(Rock, Paper)
}

The other thing I was hoping for was to be able to destructure function arguments, but alas twas not to be. I had:

list.map(fn(game: List(Move)) {
  let [a, b] = game
  move.compare(a, b)
})

…and I really wanted to be able to get rid of the let statement like so:

list.map(fn([a, b]) {
  move.compare(a, b)
})

Which is unfortunately not currently possible.

I would say these are really minor, though. The benefit of using Gleam is that you can depend on types when you want with an Elixir-like paradigm. The error messages are great, at one point reminding me when I was trying to use result.is_ok() that Gleam is not an object oriented language, and that I would probably be better off using Result.is_ok(result).

Pipes are also great. I feel like I’m making Super Mario Maker with all the pipes I’m putting in. For instance, you could write the above Result code like so:

result
|> Result.is_ok()

Gleam is smart enough to use the result of the last computation as the first argument in the next one. But if you want, you can also reference the last result as an underscore in case you need to pass it in to a different positional argument:

100
|> int.random(0, _)

There are a bunch of other cool things about the language but I have to go because my children are hangrily destroying things. Oh! The LSP server and automatic todo annotations are awesome. Okay, gotta go.

Have a terrifying AI generated image:

Stable diffusion prompt: an 8-bit pixel of Mario jumping through silicon motherboard pipes for the hero image of a blog post

PIPES

Leave a Reply

Your email address will not be published. Required fields are marked *