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
- Language tour
- Official website
- Discord server
- Github
- Cheat sheets
- Awesome Gleam resource list
- Standard library documentation
- Gleam package index
gleam.toml
file reference- Command line reference (for
gleam
command) - Gleam's threads on the Erlang Forums
- Gleam discussions on Github
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 whattest()
returns, the result of the&&
operator isFalse
. However, if we will changeFalse
toTrue
: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 is0
: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 implicitInt
toFloat
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 to2.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)