Crystal Cheat Sheet
Core Crystal syntax covering static typing, classes, collections, and blocks for a Ruby-like compiled language.
2 PagesIntermediateApr 12, 2026
Basics
Variables, interpolation, and methods.
crystal
# Variables and printingname = "World"puts "Hello, #{name}!" # string interpolationx = 42 # type inferred as Int32def add(a, b) a + bendputs add(2, 3)
Static Types
Explicit types, nilable types, and unions.
crystal
x : Int32 = 42y : Float64 = 3.14s : String = "text"n : Int32? = nil # nilable type (union with Nil)def describe(x : Int32 | String) case x when Int32 puts "int: #{x}" when String puts "string: #{x}" endend
Classes
Inheritance and instance variables.
crystal
class Animal property name : String def initialize(@name : String) end def speak "#{name} makes a sound" endendclass Dog < Animal def speak "#{name} barks" endendputs Dog.new("Rex").speak
Collections
Arrays and hashes.
- [1, 2, 3]- Array(Int32) literal
- {"a" => 1, "b" => 2}- Hash(String, Int32) literal
- arr.map { |x| x * 2 }- Transforms each element
- arr.select { |x| x > 1 }- Filters elements matching a condition
- arr.each { |x| puts x }- Iterates over elements
- arr << 4- Appends an element (alias for push)
Blocks & Procs
Yielding and typed procs.
- def each(&block)- Method that accepts a block argument
- yield x- Invokes the block passed to the current method
- ->(x : Int32) { x * 2 }- Typed Proc literal
- arr.each_with_index { |x, i| }- Iterates with an index
- 1.upto(5) { |i| }- Iterates an inclusive numeric range
- String.build { |s| s << "x" }- Efficiently builds a string
Modules & Mixins
include and extend for shared behavior.
crystal
module Greetable def greet "Hi, I'm #{name}" endendclass Person include Greetable # instance methods getter name : String def initialize(@name : String); endendputs Person.new("Ana").greetmodule Config extend self # methods become module-level class_property env = "dev"end
Fibers & Channels
Concurrency with spawn and Channel.
crystal
channel = Channel(Int32).newspawn do 10.times { |i| channel.send(i) } channel.closeendwhile value = channel.receive? puts valueend# run many fibers and waitwg = WaitGroup.new(3)3.times { spawn { do_work; wg.done } }wg.wait
Macros
Compile-time code generation with macros.
crystal
macro define_getters(*names) {% for name in names %} def {{name.id}} @{{name.id}} end {% end %}endclass Point def initialize(@x : Int32, @y : Int32); end define_getters x, yend# {{ }} pastes, {% %} evaluates at compile time
Nil & Union Types
Working safely with nilable values.
- String?- shorthand for the union String | Nil
- value.try &.upcase- call method only if value is not nil, else nil
- value.not_nil!- assert non-nil; raises NilAssertionError if nil
- value || default- provide a fallback when value is nil/false
- if x = maybe_nil- assign + guard; narrows x to non-nil inside the block
- .as(String)- restrict a union type to one member (raises on mismatch)
Tooling & Commands
Everyday shards and compiler commands.
- crystal run file.cr- compile and run in one step
- crystal build --release file.cr- optimized production binary
- crystal spec- run specs in the spec/ directory
- shards install- install dependencies from shard.yml
- crystal tool format- auto-format source files
- crystal docs- generate API documentation from comments
Pro Tip
Crystal's type inference is compile-time and static despite Ruby-like syntax — build with crystal build --release for optimized binaries, since debug builds are noticeably slower.
Was this cheat sheet helpful?
Explore Topics
#Crystal#CrystalCheatSheet#Programming#Intermediate#StaticTypes#Classes#Collections#BlocksProcs#OOP#DataStructures#CheatSheet#SkillVeris