GitHub Repository Forum RSS-Newsfeed

Crystal

A language for humans and computers

Examples

Batteries included

Crystal’s standard library comes with a whole range of libraries that let you start working on your project right away.

# A very basic HTTP server
require "http/server"

server = HTTP::Server.new do |context|
  context.response.content_type = "text/plain"
  context.response.print "Hello world, got #{context.request.path}!"
end

address = server.bind(8080)
puts "Listening on http://#{address}"

# This call block until the process is terminated
server.listen

Type system

Crystal is statically typed and type errors are caught early by the compiler, eliminating a range of type-related errors at runtime.

Yet type annotations are rarely necessary, thanks to powerful type inference. This keeps the code clean and feels like a dynamic language.

def shout(x)
  # Notice that both Int32 and String respond_to `to_s`
  x.to_s.upcase
end

# If `ENV["FOO"]` is defined, use that, else `10`
foo = ENV["FOO"]? || 10

puts typeof(foo) # => (Int32 | String)
puts typeof(shout(foo)) # => String

Null reference checks

nil values are represented by a special type, Nil, and any value that can be nil has a union type including Nil.

As a consequence, the compiler can tell whether a value is nilable at compile time. It enforces explicit handling of nil values, helping prevent the dreadful billion-dollar mistake.

foo = [nil, "hello world"].sample

# The type of `foo` is a union of `String` and `Nil``
puts typeof(foo) # => String | Nil

# This would be a type error:
# puts foo.upcase # Error: undefined method 'upcase' for Nil

# The condition excludes `Nil` and inside the branch `foo`'s type is `String`.
if foo
  puts typeof(foo) # => String
  puts foo.upcase
end

Syntax

Crystal’s syntax is heavily inspired by Ruby’s, so it feels natural to read and easy to write, and has the added benefit of a lower learning curve for experienced Ruby devs.

class String
  def longest_repetition?
    max = chars
            .chunk(&.itself)
            .map(&.last)
            .max_by?(&.size)

    {max[0], max.size} if max
  end
end

puts "aaabb".longest_repetition? # => {'a', 3}

Concurrency Model

Crystal uses green threads, called fibers, to achieve concurrency. Fibers communicate with each other via channels without having to turn to shared memory or locks (CSP).

channel = Channel(Int32).new

3.times do |i|
  spawn do
    3.times do |j|
      sleep rand(100).milliseconds # add non-determinism for fun
      channel.send 10 * (i + 1) + j
    end
  end
end

9.times do
  puts channel.receive
end

C-bindings

Crystal allows to define bindings for C libraries and call into them. You can easily use the vast richness of library ecosystems available.

No need to implement the entire program in Crystal when there are already good libraries for some jobs.

# Define the lib bindings and link info:
@[Link("m")]
lib LibM
  fun pow(x : LibC::Double, y : LibC::Double) : LibC::Double
end

# Call a C function like a Crystal method:
puts LibM.pow(2.0, 4.0) # => 16.0

# This example intentionally uses a simple standard C function to be succinct.
# Of course you could do *this specific* calculation in native Crystal as well:
# 2.0 ** 4.0 # => 16.0

Macros

Crystal’s answer to metaprogramming is a powerful macro system, which ranges from basic templating and AST inspection, to types inspection and running arbitrary external programs.

class Object
  def has_instance_var?(name) : Bool
    {{ @type.instance_vars.map &.name.stringify }}.includes? name
  end
end

class Person
  property name : String

  def initialize(@name)
  end
end

person = Person.new "John"
p! person.has_instance_var?("name") # => true
p! person.has_instance_var?("birthday") # => false

Dependencies

Crystal libraries are packed with Shards, a distributed dependency manager without a centralised repository.

It reads dependencies defined in shard.yml and fetches the source code from their repositories.

name: my-first-crystal-app
version: 1.0.0
license: Apache-2.0

authors:
- Crys <crystal@manas.tech>

dependencies:
  mysql:
    github: crystal-lang/crystal-mysql
    version: ~>0.16.0

development_dependencies:
  ameba:
    github: crystal-ameba/ameba

News


Sponsorship

Become a Crystal sponsor in only 3 simple steps via OpenCollective

Contribute
Enterprise support

Sponsoring Crystal creates a great springboard for your brand

Get Support
Hire us for your project

You can tap into the expertise of the very creators of the language to guide you in your implementation.

Hire Us

Top Sponsors

Success stories