Beginner

Hello World in Crystal

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

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

The Code

Create a file named hello.cr:

1
puts "Hello, World!"

That’s it! If you know Ruby, this looks identical - and that’s by design.

Understanding the Code

  • puts - Prints a string to standard output followed by a newline
  • "Hello, World!" - A String literal enclosed in double quotes
  • No semicolon - Crystal doesn’t require semicolons at the end of statements
  • No main function - Top-level code runs automatically

Running with Docker

The easiest way to run this without installing Crystal locally:

1
2
3
4
5
# Pull the official Crystal image
docker pull crystallang/crystal:1.14.0

# Run the program
docker run --rm -v $(pwd):/app -w /app crystallang/crystal:1.14.0 crystal run hello.cr

Running Locally

If you have Crystal installed:

1
2
3
4
5
6
# Run directly (compiles and executes)
crystal run hello.cr

# Or compile to a binary first
crystal build hello.cr
./hello

Expected Output

Hello, World!

Key Concepts

  1. Ruby-like syntax - Crystal intentionally mirrors Ruby’s clean, readable style
  2. Compiled language - Despite the scripting feel, Crystal compiles to native code
  3. Type inference - The compiler automatically determines types
  4. crystal run - Compiles and runs in one step (great for development)
  5. crystal build - Creates an optimized standalone binary

A More Detailed Version

For a slightly more structured approach showing Crystal’s type system:

1
2
3
4
5
6
7
8
# A typed greeting function
def greet(name : String) : String
  "Hello, #{name}!"
end

# Call the function and print the result
message = greet("World")
puts message

This version demonstrates:

  • Function definition - Using def with type annotations
  • Type annotations - name : String and return type : String
  • String interpolation - Embedding values with #{}
  • Type inference - message is automatically typed as String

Object-Oriented Approach

Crystal is fully object-oriented:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Greeter
  def initialize(@name : String)
  end

  def greet
    puts "Hello, #{@name}!"
  end
end

greeter = Greeter.new("World")
greeter.greet

Key features shown:

  • @name - Instance variable with shorthand initialization
  • Constructor - initialize method runs when creating instances
  • Classes - Full OOP support with inheritance and polymorphism

Why Crystal Stands Out

Coming from other languages, you’ll notice Crystal’s unique characteristics:

  • Ruby syntax, C speed - Write beautiful code that runs fast
  • Nil safety - Compiler catches null reference errors
  • No runtime - Compiles to efficient native binaries
  • Great error messages - Clear, helpful compiler feedback

Compile vs Run Performance

1
2
3
4
5
6
# Development: compile + run (slower, for iteration)
time crystal run hello.cr

# Production: build optimized binary
crystal build --release hello.cr
time ./hello

The --release flag enables optimizations, producing highly efficient executables.

Next Steps

Continue to Variables and Data Types to learn about Crystal’s powerful type system, including union types, nil safety, and the balance between explicit typing and inference.

Running Today

All examples can be run using Docker:

docker pull crystallang/crystal:1.14.0
Last updated: