Hello World in Gleam
Your first Gleam program - the classic Hello World example with Docker setup
Every programming journey starts with Hello World. Let’s write our first Gleam program.
The Code
Create a file named hello.gleam:
| |
Three lines to print to the console - clean and readable.
Understanding the Code
import gleam/io- Imports theiomodule from the standard library for console outputpub fn main()- Defines the publicmainfunction, which is the program’s entry pointio.println()- Prints a string to standard output with a newline- Curly braces - Gleam uses C-family style syntax with curly braces for blocks
Running with Docker
Gleam requires a project structure to run. The easiest way to try it without installing locally is with Docker:
| |
Why the Extra Steps?
Unlike scripting languages, Gleam uses a project-based build system (similar to Rust’s Cargo). The gleam new command creates the project structure with a gleam.toml manifest and dependency configuration. The command above automates this by:
- Creating a new project called
hello - Copying your source file into the project’s
src/directory - Running
gleam runto compile and execute
Running Locally
If you have Gleam installed (along with Erlang):
| |
Install Gleam via:
| |
Note: Gleam also requires Erlang to be installed for the BEAM compilation target.
Expected Output
Hello, World!
Key Concepts
- Static types - Gleam checks types at compile time, catching errors before your code runs
- Type inference - The compiler figures out types automatically; you rarely need annotations
- Module system - Functions live in modules (like
gleam/io), imported explicitly - No semicolons - Expressions are separated by newlines
- BEAM VM - Compiles to Erlang bytecode, running on the battle-tested Erlang virtual machine
Project Structure
When you create a Gleam project with gleam new, you get:
hello/
├── gleam.toml # Project manifest (name, version, dependencies)
├── src/
│ └── hello.gleam # Your source code
└── test/
└── hello_test.gleam # Tests
The gleam.toml file manages dependencies from Hex, the package repository shared with Erlang and Elixir.
A More Gleam-Style Example
| |
This demonstrates:
letbindings - Immutable variable assignment- Private functions -
fnwithoutpubis module-private - Type annotations - Optional but useful for documentation
- String concatenation - Using the
stringmodule from the standard library
Pattern Matching
Gleam’s case expression is powerful:
| |
The compiler ensures you handle every possible case - if you miss one, it tells you at compile time.
The Pipe Operator
Gleam’s pipe operator (|>) chains function calls, passing the result of each as the first argument to the next:
| |
Data flows top to bottom, making transformations easy to follow.
Result Type for Error Handling
Gleam uses the Result type instead of exceptions:
| |
This forces you to handle both success and failure cases explicitly - no uncaught exceptions.
Common Beginner Notes
No Null Values
Gleam has no null or nil. Use the Option type for values that might not exist:
| |
All Data Is Immutable
Every value in Gleam is immutable. “Updating” a value creates a new one:
| |
Erlang and Elixir Interop
Gleam can call Erlang and Elixir functions directly using external functions, giving you access to the entire BEAM ecosystem.
Running Today
All examples can be run using Docker:
docker pull ghcr.io/gleam-lang/gleam:v1.14.0-erlang-alpine