An Introduction to Crystal
February 21, 2021
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!
- Awesome Crystal List A big list of Crystal code and resources
- Crystal Reference The Crystal Team’s own language reference
- Crystal API Docs Crystal’s API docs for working with the standard library
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