Oisin's Blog

An Introduction to Crystal

February 21, 2021

Crystal logo

One of my favourite programming languages in the last few years has been Crystal. While the language has not yet reached its 1.0 version, it has been widely used in production and has a growing ecosystem. Crystal provides an easy setup and allows you to jump straight into developing your own Crystal programs. I’m going to walk you through getting it setup and how you can get started!

puts "Hello World"

Crystal is a general purpose, Ruby-inspired compiled programming language, making it extremely fast and easy to program with. The syntax is strongly inspired by Ruby, but also provides static typechecking. Crystal sits somewhere in the top 100 programming languages according to TIOBE, not widely used but don’t let that put you off!

I was originally interested in Crystal due to its expressive syntax and the claims on its speed. I am likely in the minority in that I came into Crystal with no prior Ruby experience. Crystal soon became my go-to language for personal programming projects. My project Azula (WIP programming language) was built entirely in Crystal - a choice a made due to Crystal’s nice macro system and built-in LLVM bindings. Crystal was an excellent choice, allowing rapid development and producing a small binary (1.9mb in Crystal vs 3mb in Go).

Shards

The Crystal ecosystem is powered by its Shard system. Shards is Crystal’s dependency manager that is usually installed along with Crystal. It aims to allow reproducible installs across platforms by declaring dependencies and their versions. You can read more about Shards here.

Installing Crystal

On Ubuntu, installing Crystal is as easy as running:

$ curl -fsSL https://crystal-lang.org/install.sh | sudo bash

For other platforms, have a look at the Crystal install guide!

First Crystal Program

Crystal provides a nice scaffolding tool to setup a new project, including a README template, license and gitignore.

$ crystal init app myproject

If we open up myproject/src/myproject.cr, we can start writing our Crystal program!

def say(message : String) puts message end say "Hello!"

In this example, we create a function called say that accepts a string and passes it to puts. As you can see, almost identical to Ruby except for the typing of the parameter in the function.

Project Structure

src

Inside the src/ directory is where all the Crystal files will go. It can contain subdirectories, allowing you to divide up your code. You can include separate files by using the require keyword.

spec

The spec/ directory is the home for your tests. Using the crystal spec subcommand, we can run all our tests.

it "works" do i = 5 + 10 i.should eq 15 end

shard.yml

shard.yml is used to define our project. In here, we define the name, version, authors, Crystal version, licence & dependencies.

name: myproject version: 0.1.0 authors: - OisinA targets: myproject: main: src/myproject.cr crystal: 0.36.1 license: MIT

Building & Running

Running

$ crystal run src/myproject.cr Hello!

Running your Crystal project is as simple as running crystal run [file].

Building

$ crystal build src/myproject.cr $ ./myproject Hello!

To build your project, you use crystal build [file] producing an executable. You can optionally use the --release optimising the executable. This flag will significantly increase the build time but the produced binary should be smaller and faster.

Crystal’s build times are reasonable. Compiling my project Azula takes ~16s with the release flag. Compiling our barebones project above takes ~8s.

Example

Simple Web Server

In this example, I am using Kemal, a HTTP framework for Crystal, to set up a really simple web server to return some JSON on a request. Kemal makes it really easy to quickly write a web application and has built-in JSON support, static file serving and templating. Kemal is installed using Crystal Shards, adding it to the shards.yml.

require "kemal" require "json" get "/" do |env| env.response.content_type = "application/json" {name: "Oisin", time: Time.local}.to_json end Kemal.run

Running this will start up a HTTP server on port 3000, returning JSON containing name and the current time.

$ curl http://localhost:3000 {"name":"Oisin","time":"2021-02-21T18:07:46+00:00"}

It’s as simple as that!

The Future of Crystal

With Crystal being in a nice place at the moment - what are the next steps? The next step for Crystal is to reach a 1.0 release. This version of Crystal will be completely stable and fully ready for production. The Crystal team are currently working towards this goal currently. While there is no timeline in place, its an exciting prospect! I am excited for the future of Crystal and hope to see it more widely used.

Resources

If you’ve enjoyed this blog post, you might be interested in reading more about Crystal and its ecosystem. I’ll list some links here and feel free to reach out to me on Twitter if you have any questions!

Footnotes:

  • @osslate For proof-reading and giving nice criticism <3
  • Towards 1.0 Information about Crystal’s upcoming 1.0 release

Written by Oisin Aylward, a Software Engineer from Ireland. Follow me on Twitter