What is Gleam?

Gleam is a friendly language for building type-safe, scalable systems!

It compiles to Erlang (or JavaScript) and has straightforward interop with other BEAM languages such as Erlang, Elixir, and LFE.

For more information see the Gleam website: https://gleam.run.

Hello world written in Gleam:

import gleam/io

pub fn main() {
  io.println("hello, world!")
}

The power of a type system, the expressiveness of functional programming, and the reliability of the highly concurrent, fault tolerant Erlang runtime, with a familiar and modern syntax.

Reliable and scalable

Running on the battle-tested Erlang virtual machine that powers planet-scale systems such as WhatsApp and Ericsson, Gleam is ready for workloads of any size.

Thanks to a multi-core actor based concurrency system that can run millions of concurrent tasks, fast immutable data structures, and a concurrent garbage collector that never stops the world, your service can scale and stay lightning fast with ease.

fn spawn_task(i) {
  task.async(fn() {
    let n = int.to_string(i)
    io.println("Hello from " <> n)
  })
}

pub fn main() {
  // Run loads of threads, no problem
  list.range(0, 200_000)
  |> list.map(spawn_task)
  |> list.each(task.await_forever)
}

Ready when you are

Gleam comes with compiler, build tool, formatter, editor integrations, and package manager all built in, so creating a Gleam project is just running gleam new.

As part of the wider BEAM ecosystem, Gleam programs can use thousands of published packages, whether they are written in Gleam, Erlang, or Elixir.

➜ (main) gleam add gleam_json
  Resolving versions
Downloading packages
 Downloaded 2 packages in 0.01s
      Added gleam_json v0.5.0
➜ (main) gleam test
 Compiling thoas
 Compiling gleam_json
 Compiling app
  Compiled in 1.67s
   Running app_test.main
.
1 tests, 0 failures

Here to help

No null values, no exceptions, clear error messages, and a practical type system. Whether you're writing new code or maintaining old code, Gleam is designed to make your job as fun and stress-free as possible.

error: Unknown record field

  ┌─ ./src/app.gleam:8:16
  │
8 │ user.alias
  │     ^^^^^^ Did you mean `name`?

The value being accessed has this type:
    User

It has these fields:
    .name

Multilingual

Gleam makes it easy to use code written in other BEAM languages such as Erlang and Elixir, so there's a rich ecosystem of thousands of open source libraries for Gleam users to make use of.

Gleam can additionally compile to JavaScript, enabling you to use your code in the browser, or anywhere else JavaScript can run. It also generates TypeScript definitions, so you can interact with your Gleam code confidently, even from the outside.

@external(erlang, "Elixir.HPAX", "new")
pub fn new(size: Int) -> Table

pub fn register_event_handler() {
  let el = document.query_selector("a")
  element.add_event_listener(el, fn() {
    io.println("Clicked!")
  })
}

Helpful links

Installation

Erlang

As Gleam compiler transpiles mainly to erlang and additionally javascript, it requires erlang to work. So if you are on Linux or MacOS, you can use one of:

  • For Homebrew on macOS: brew install erlang.
  • For MacPorts on macOS: port install erlang.
  • For Ubuntu and Debian: apt-get install erlang.
  • For Fedora: yum install erlang.
  • For ArchLinux and Manjaro: pacman -S erlang.
  • For FreeBSD: pkg install erlang.

If you are on Windows, use 64-bit or 32-bit installers.

Releases

To install Gleam, go to releases tab on the github repo. Find the last release and install the corresponding version.

Building from source

In some cases, you want to build Gleam compiler from source. For example, when you need to use it in web using webassembly or you want to contribute. First clone the Gleam git repo:

git clone https://github.com/gleam-lang/gleam
cd gleam

Gleam compiler is written in Rust, so you need to have Rust installed on your system.

If you are on Linux/Mac, you can install rustup using this shell command:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

rustup installs Rust programming language from the official release channels. To install latest stable of Rust, use rustup toolchain install.

If you are on Windows, go to the Rust official website and click to the download rustup-init.exe button. Then run the downloaded exe file and run shell command: rustup toolchain install.

After installing Rust, run:

cargo install --path compiler-cli

In the Gleam repo folder, and you will get Gleam compiler installed on your system.

In case, you need version of the Gleam compiler for WebAssembly, you need to first install wasm-pack:

curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

If you are on Windows, you can alternatively install it from source:

cargo install wasm-pack

Then run:

cd compiler-wasm
wasm-pack build --target web

Hello World

Let us now write our first Gleam program! If you don't have Gleam installed, it is recommended to follow instructions in the previous section. Run:

gleam new hello_world
cd hello_world

You can now see the automatically generated Gleam project structure:

hello_world
|_ .github/workflows
   |_ test.yml
|_ src
   |_ hello_world.gleam
|_ test
   |_ hello_world_test.gleam
|_ .gitignore
|_ gleam.toml
|_ README.md

The entry point is located in the src/hello_world.gleam file. It will probably look something like this:

import gleam/io

pub fn main() {
  io.println("Hello from hello_world!")
}

Let us change our program, so that it prints canonical Hello, world! message:

import gleam/io

pub fn main() {
  io.println("Hello, world!")
}

As you can see, Gleam doesn't require semicolons. To run the program, you can use gleam run command:

$ gleam run
  Compiling gleam_stdlib
  Compiling gleeunit
  Compiling hello_world
   Compiled in 1.78s
    Running hello_world.main
Hello, world!

By default, it transpiles our code to erlang and uses it to run our code. However, you can also use javascript using --target flag:

$ gleam run --target javascript
  Compiling gleam_stdlib
  Compiling gleeunit
  Compiling hello_world
   Compiled in 1.5s
    Running hello_world.main
Hello, world!

You can also use specific javascript runtime using --runtime flag:

$ gleam run --target javascript --runtime node
  Compiling gleam_stdlib
  Compiling gleeunit
  Compiling hello_world
   Compiled in 1.5s
    Running hello_world.main
Hello, world!

Comments

Let us now modify our previous hello world program:

import gleam/io

pub fn main() {
  // Print hello world
  io.println("Hello world!")
}

Gleam allows you to write comments in your code. In Gleam, comments must start with two slashes and continue until the end of the line. For comments that extend beyond a single line, you’ll need to include // on each line, like this:

// Hello, world! I have a lot to say, so much that it will take multiple
// lines of text. Therefore, I will start each line with // to denote it
// as part of a multi-line comment.

Comments don't have any semantic meaning and don't affect the way the program behaves. Instead, they are used for clarity and for documenting your code.

Booleans

In Gleam, boolean literal is either True or False. Its type is Bool. Here are some basic operations with booleans:

False && False // => False
False && True  // => False
True && False  // => False
True && True   // => True

False || False // => False
False || True  // => True
True || False  // => True
True || True   // => True

&& and || are short circuiting, meaning they don't evaluate the right hand side if they don't have to.

&& evaluates the right hand side if the left hand side is True. So it is literally a name for "logical AND". So it returns True only if all two inputs are True.

|| evaluates the right hand side if the left hand side is False. So it is literally a name for "logical OR". So it returns False only if all two inputs are False.

If you want to print boolean with io.println function, you need to first convert it to String using bool.to_string:

import gleam/io
import gleam/bool

pub fn main() {
  io.println(
    bool.to_string(True),
  )
}

Output:

True

Note: you can alternatively use io.debug, if you want to print any type you want:

import gleam/io

pub fn main() {
  io.debug(False)
  io.debug("True")
}

Output:

False
True

Gleam also supports negation of Bools using either the ! operator or the bool.negate function from the gleam/bool module:

import gleam/io
import gleam/bool

pub fn main() {
  io.debug(!True)
  io.debug(bool.negate(False))
}

Output:

False
True

Important: && and || are short circuiting, meaning they don't evaluate the right hand side if they don't have to. Example:

import gleam/io

fn test() -> Bool {
   io.println("test")
   True
}

pub fn main() {
   io.debug(False && test())
}

Output:

False

Here "test" wasn't printed, because no matter what test() returns, the result of the && operator is False. However, if we will change False to True:

import gleam/io

fn test() -> Bool {
   io.println("test")
   True
}

pub fn main() {
   io.debug(True && test())
}

"test" will be printed:

test
True

Note: calls like this:

io.debug(True)

Can be simplified, using the pipe operator (|>):

True |> io.debug

Another example:

import gleam/io
import gleam/bool

pub fn main() {
  True
  |> bool.to_string
  |> io.println
}

Numbers

Gleam has two main types for numbers: Int for whole numbers and Float for numbers with a decimal point.

Integers

Integers in Gleam are written as usual:

1
2
3
-4
2942930103

Gleam supports _ in integers for clarity:

3_000_000

In the given example, the _ has no syntactic and semantic meaning.

Gleam as many other languages also supports integers in different bases: binary, octal and hexadecimal integers start with 0b, 0o and 0x respectively:

0b0101000101
0o712
0xFf // `f` and `F` here are the same

Gleam supports basic primitive operations with integers:

1 + 3 - 2 * 4 // => -4
7 / 2  // => 3 (rounded)
3 % 2  // => 1
1 > 0  // => True
1 < 0  // => False
1 >= 0 // => True
1 <= 0 // => False

Note: In Gleam division between integers returns another integer, which is the result of the division rounded down.

Note: In Gleam division doesn't handle edge case with divisor being 0:

2 / 0 // => 0
1 / 0 // => 0
0 / 0 // => 0

This is why it is generally recommended to use int.divide function which returns an error if the divisor is 0:

5 |> int.divide(2) // => Ok(2)
5 |> int.divide(0) // => Error(Nil)
0 |> int.divide(0) // => Error(Nil)

To print the integer in Gleam, you need to first convert it to string. You can do that using int.to_string function:

import gleam/io
import gleam/int

fn main() {
  io.println(3 |> int.to_string)
}

Note: There is currently no maximum value for integers in Gleam, however there is a difference in behaviour for javascript and erlang targets for converting big integers to strings. Example:

import gleam/io
import gleam/int

fn main() {
  io.println(9_999_999_999_999_999 |> int.to_string)
}

Output when running the code using default erlang target (gleam run):

9999999999999999

Output when running the code using javascript target (gleam run --target javascript):

10000000000000000

You can find the absolute value of the integer using int.absolute_value function:

-12 |> int.absolute_value // => 12
12  |> int.absolute_value // => 12
0   |> int.absolute_value // => 0

If you want the result of the base being raised to the power of exponent, you can use power function:

3 |> int.power(of: 2.0) // => 9
2 |> int.power(of: 2.0) // => 4
2 |> int.power(of: 4.0) // => 16

Note: power accepts second argument only as floating point number. Gleam doesn't have implicit Int to Float cast:

error: Type mismatch
   ┌─ /gleam-tutorial/hello_world/src/hello_world.gleam
   │
   │  3 |> int.power(of: 2)
   │                     ^

Expected type:

    Float

Found type:

    Int

So 2 must be changed to 2.0. See the floating point numbers section below.

If you want to convert an integer to float, you can use to_float function:

3  |> to_float // 3.0
-3 |> to_float // -3.0
0  |> to_float // 0.0

Here are some other useful methods for integers:

// Returns the minimum of two numbers
int.min(2, 3)    // => 2

// Returns the maximum of two numbers
int.max(3, 4)    // => 4

// Returns true if the number is even
2 |> int.is_even // => True
3 |> int.is_even // => False

// Returns true if the number is odd
2 |> int.is_odd  // => False
3 |> int.is_odd  // => True

// Returns the negative of the number
1 |> int.negate  // => -1

// Returns the square root of the number
4   |> int.square_root // => Ok(2.0)
-16 |> int.square_root // => Error(Nil)

You can convert integers to different common bases:

2  |> to_base2 // => "10"
15 |> to_base8 // => "17"
48 |> to_base16 // => "30"
48 |> to_base36 // => "1C"

If you want to convert a number to any base from 2 to 36, you can use to_base_string:

// 37 is bigger than 36
48 |> to_base_string(37) // => Error(InvalidBase)

// 1 is less than 2
48 |> to_base_string(1)  // => Error(InvalidBase)

// Same as running to_base36()
48 |> to_base_string(36) // => Ok("1C")

Floating-point numbers

Float-s are numbers that have a decimal point:

1.6
-0.3
8.0

As for integers, Gleam supports _ in floats for clarity:

3.141_159_265

Note: you cannot put _ before .:

error: Syntax error
   ┌─ .../hello_world/src/hello_world.gleam
   │
   │     -0_.3_3
   │       ^ Numbers cannot have a trailing underscore

Hint: remove it.

You can also use scientific notation with floats:

2.997e8
6.626e-34

Note: In Gleam operators like +, -, * and / cannot be used for floats. Instead use +., -., *. and /.:

2.0 +. 2.0 // => 4.0
3.0 -. 2.0 // => 1.0
1.0 *. 2.0 // => 2.0
3.0 /. 2.0 // => 1.5

// As with integers
2.0 /. 0.0 // => 0.0
0.0 /. 0.0 // => 0.0

Note: It is a little more difficult with comparison operators. == and != work for both integers and floats. >, <, >=, <= however only work for integers. So you need to use analogs: >., <., >=., <=.:

2.0 >.  1.0  // => True
2.0 <=. 2.0  // => True
2.0 <.  2.0  // => True
2.0 ==  2.0  // => True
2.0 !=  2.0  // => False

Note: In Gleam as with integers division doesn't handle edge case with divisor being 0.0:

2.0 /. 0.0 // => 0.0
1.0 /. 0.0 // => 0.0
0.0 /. 0.0 // => 0.0

This is why it is generally recommended to use float.divide function which returns an error if the divisor is 0:

import gleam/float

5.0 |> float.divide(2.0) // => Ok(2.5)
5.0 |> float.divide(0.0) // => Error(Nil)
0.0 |> float.divide(0.0) // => Error(Nil)

You can find the absolute value of the float using float.absolute_value function:

-12.0 |> float.absolute_value // => 12.0
12.0  |> float.absolute_value // => 12.0
0.0   |> float.absolute_value // => 0.0

You can also round float number to the next lowest or the next highest whole number using ceiling and floor functions:

2.3 |> float.ceiling // => 3.0
2.3 |> float.floor   // => 2.0

Or you can round to the nearest whole number using round:

2.3 |> float.round // => 2.0
2.5 |> float.round // => 3.0

Here are some other useful methods for floats:

// Returns the minimum of two numbers
float.min(2.0, 3.3)             // => 2.0

// Returns the maximum of two numbers
float.max(3.1, 4.2)             // => 4.2

// Returns the negative of the number
1.0 |> float.negate             // => -1.0

// Returns the value as `Int`, truncating all decimal digits
2.4287898428 |> float.truncate  // => 2

// Returns the results of the base being raised to the power of the exponent
2.0  |> float.power(-1.0)    // => Ok(0.5)
2.0  |> float.power(2.0)     // => Ok(4.0)
4.0  |> float.power(of: 2.0) // => Ok(16.0)
-1.0 |> float.power(0.5)     // => Error(Nil)

// Returns the square root
4.0   |> float.square_root   // => Ok(2.0)
-16.0 |> float.square_root   // => Error(Nil)

Variables

Tuples and lists

Functions

Expression blocks

Strings

Pipe operator

Nil

Result

Pattern matching

Panic and assert

Creating custom types

Type aliases

Todo

Let assertions

Constants

Modules and imports

Use

Bit strings

escape sequences

Generics

Tail call optimisation

Phantom types

Labelled arguments

Labelled fields

Dict

Pairs

Sets

Option

Order

Iterator

Opaque types

Queue

Erlang and Javascript interop

Testing

Bytes and string builders

Base64

Regex

URI

Installing custom packages

Creating and publishing a package

Gleam docker images

Simplifile package

Filepath: filepath

Ranges: ranger

Datetime: birl

Ad-hoc error type: snag

Json: gleam_json

gleam_crypto