Beginner

Hello World in Elixir

Your first Elixir program - the classic Hello World example with Docker setup

Every programming journey starts with Hello World. Let’s write our first Elixir program.

The Code

Create a file named hello.exs:

1
IO.puts("Hello, World!")

That’s it! One line to print to the console.

Understanding the Code

  • IO.puts() - Prints a string to standard output with a newline. IO is a module, puts is a function.
  • .exs extension - Elixir script file. Interpreted directly without compilation.
  • Parentheses optional - IO.puts "Hello, World!" also works, but explicit parens are clearer.

Running with Docker

The easiest way to run this without installing Elixir locally:

1
2
3
4
5
# Pull the Elixir image
docker pull elixir:1.17-alpine

# Run your script
docker run --rm -v $(pwd):/app -w /app elixir:1.17-alpine elixir hello.exs

Running Locally

If you have Elixir installed:

1
2
# Run the script directly
elixir hello.exs

Or use the interactive shell (IEx):

1
2
3
4
5
6
7
# Start interactive Elixir
iex

# Then type:
iex> IO.puts("Hello, World!")
Hello, World!
:ok

Expected Output

Hello, World!

Key Concepts

  1. Functional language - Functions are the primary building blocks
  2. Immutable data - Values can’t be changed after creation
  3. .exs vs .ex - Scripts (.exs) vs compiled modules (.ex)
  4. Module.function() - Functions live in modules (like IO.puts)
  5. BEAM VM - Runs on the Erlang virtual machine

.exs vs .ex Files

  • .exs - Script files, interpreted each time, used for scripts and tests
  • .ex - Source files, compiled to bytecode, used for application code

For quick scripts like Hello World, .exs is perfect.

A More Elixir-Style Example

1
2
3
4
5
6
7
defmodule Greeter do
  def hello(name) do
    "Hello, #{name}!"
  end
end

IO.puts(Greeter.hello("World"))

This demonstrates:

  • defmodule - Defines a module (container for functions)
  • def - Defines a public function
  • String interpolation - #{expression} embeds values in strings
  • Implicit return - The last expression is returned automatically

Pattern Matching Example

Elixir’s pattern matching is powerful:

1
2
3
4
5
6
7
defmodule Greeter do
  def hello("World"), do: "Hello, World! (special case)"
  def hello(name), do: "Hello, #{name}!"
end

IO.puts(Greeter.hello("World"))   # Hello, World! (special case)
IO.puts(Greeter.hello("Elixir"))  # Hello, Elixir!

Different function clauses match different inputs—no if statements needed!

The Pipe Operator

Elixir’s pipe operator (|>) chains function calls:

1
2
3
4
"world"
|> String.capitalize()
|> (fn name -> "Hello, #{name}!" end).()
|> IO.puts()

Data flows left to right, making transformations readable.

Interactive Elixir (IEx)

IEx is great for exploration:

1
2
3
4
5
6
$ iex
iex> "Hello" <> ", " <> "World!"
"Hello, World!"
iex> String.upcase("hello")
"HELLO"
iex> h IO.puts  # Get help on any function

The h helper shows documentation for any function right in the shell.

Next Steps

Continue to Variables and Pattern Matching to learn about Elixir’s powerful pattern matching and immutable variables.

Running Today

All examples can be run using Docker:

docker pull elixir:1.17-alpine
Last updated: