Discovering Crystal

Original post can be found in the ApiumHub blog.

Another in the series. Check out other languages we’ve explored in the past at:

A bit of background about me before we begin our exploration of a new programming language.

I’ve been in love with programing languages for a couple of years now. I’m very interested in their semantics, the reasoning of why their designers chose to do X over Y, and why they outright discarded Z. I’ve done my fair share of DSLs in my tenure as a software developer for both fun and profit; so programming languages are the reasonable “step up” to be interested in.

As such I’m always in the lookout of up-and-coming languages.

Why Crystal?

Long time ago, far far away I was working with Ruby on Rails on a project with other very skilled Ruby and Rails developers. As many others working with Ruby, we liked it’s syntax, it’s ease of use, it’s dependencies (gems) but had some issues with it. Every programming language does.

Honestly, performance was not my main driver to look to other programming languages, even though in many benchmarks Crystal does excel.

I was more concerned with safety and documentation. Let me explain.


Whilst programming in Ruby, I many times had an error where an object I thought was a Hash was actually a block, or a string was in fact a number. Many times a test would just fail or panic, and it took a minute to look at the trace, maybe put a breakpoint. Pry open the execution. Realize there was a branch of the code that did not set a key in an options parameter that got passed along and I did not account for. Fix it and continue coding. undefined method ‘foo’ for nil:NilClass was particularly recurring in my development cycle.


Here I’m not referring to the actual docs I can find in Ruby Doc but rather how much information can the IDE help me out with. I’m a big proponent of making tools to help development, but having to hydrate an options hash to send to a gem’s method and having to yield to look at the gem’s code to understand what values are even available, is a big reason why I enjoy typed programing languages so much.

class FooConfiguration {
    String bar;
    Integer biz = 3

void foo(FooConfiguration options) {  }

At a glance (and with IDE support), one can deduce that foo’s options have a required bar string, and a biz that defaults to 3. Where as a similar code in Ruby could look like this:

def foo(options):
  # …
  enc = #Oh, so `bar` is a string. Gotcha!
  # ... 
  ( || 3).times { puts enc } # if `biz` is falsey, then `3`. Can I send a boolean? Oh, no, it `#.times` it, so it is a number. 🤕 
  # ...

Both these pain points were addressed, interestingly enough, by the same approach: Types.

In Crystal there is a very smart, very competent compiler that keeps track of the busy work of knowing what methods any reference might have, if it is nil or what can and can’t be done to an object. This was a godsend.

As luck would have it, I was also in close contact with some very vociferous advocate of Crystal. You can imagine, with the tagline: “Fast as C, Slick as Ruby”, I was hooked.

My breakout project, the moment I really “got” Crystal was when we needed some dashboard like solution. We realized we had built too many internal tools and no one place to cluster them all. For whatever reason we didn’t want some static lame webpage. We decided to roll out our own. Some YAML parsing, some macro goodness and a lot of type safety later we had it running. Adding apps was simple and a CI build made sure that all the things were correctly wired. It was a small project, probably way overengineered; but onboarding another Ruby developer was incredibly simple. That was a good selling point.

Why Crystal now?

That’s leading the subject, your honor!

Recently™ the nice people of Crystal announced the release of Crystal 1.0 - Production ready, stable and useful standard library all in a tight little bundle; so if it was ever the time to seriously look at Crystal; I would say today is the day. Other awesome features Type ergonomics

We talked about type safety, and some might have rolled your eyes expecting a very verbose way of writing the code; but let’s not forget one of the key drivers of Crystal is to have a similar syntax to Ruby. A dynamically typed language. So both:

class Foo                                                                  	 
  def biz
    puts "foo"

class Bar
  def biz
    puts "bar"

def invoke_biz(x)

invoke_biz( # => foo
invoke_biz( # => bar

Is both valid Ruby and Crystal. You can try that out in your browser in the crystal playground here! No type to be seen, thanks to the incredible type inference that comes with Crystal’s compiler. There is much cool things about it that I would need entire new blog posts to write, luckily Crystal’s book does a good job covering the basics: Type inference.


It’s amazing how useful it is to have such a robust parsing library already in the standard library, no need to deal with extraneous dependencies to read a configuration file, or write one out.

require "yaml"

class Bar
  include YAML::Serializable
  property biz : Float64

class Foo
  include YAML::Serializable
  property foo : String
  property bar : Bar?

That’s all the code needed to parse something like

foo: hi!
  biz: 3.2

The same holds for JSON and XML. I find it baffling how, when reading and writing configuration is so easy, much more customization I allow when developing tools with Crystal.

De-centralized shards

Maybe as I’m getting older, I’m getting more paranoid about where my dependencies (which run, for all intents and purposes, arbitrary code that gets deployed on my behalf) are fetched; but I can’t/won’t wait for a cabal to approve a new dependency. Being able to choose either a local file or any git provider gives me a bit more peace of mind.

The logo… It’s alive, it’s moving, it’s alive, it’s alive!

The black logo in the Crystal’s home page is interactive. You can click and spin it around. At first glance, one can brush off that fact, thinking it is superfluous and useless; but I would urge you to wander: Would a bad language1 such a polished home page, such well written tutorials, such active community? 🤔

Where to now?

If you are interested, you can keep learning Crystal with the book and the online playground. Have a look at the awesome-crystal compiled list of things, some might inspire you in your current or next project. Reach out.

  1. reader’s interpretation of what a bad language might be. 


Random Posts

Deckchecks, Heuristics, and Decision Trees

One of the tools judges employ to thwart attempts to cheat is to require players to write down what cards they will be playing within a particular tournament, and routinely check them. Judges must perform these checks the fastest way possible to not delay the tournament. As such, they developed a myriad of techniques. I feel we under-use the availability of the decklist, so having a clear plan ahead of actually getting the deck in our hands can prove highly effective. In this post, I would like to explore some techniques' inner workings. Propose a hypothesis on why they might work in some situations but not others. Consider unexplored alternatives. And build a heuristic on what method is better for each circumstance. Join me! #mtg

Desire Driven Development

Long have I heard and reaped the benefits of Test Driven Development. But I'm starting to sense that much of the material written and explained about TDD is by fanatics. In this post I'll explore my own take on TDD, and the journey → Desire Driven Development. #rambling #coding

The essence of Event Sourcing

Event Sourcing is a somewhat trending topic, and you can find a lot of blog posts on what event sourcing supposedly is. I’ll throw my wrench in the works and try to explain what I see as “Event Sourcing”. #xpost


¿Te pasa de querer programar algo y no saber que? tengo un bloqueo de ideas hace tiempo, quiero hacer algo con xxx y no se me ocurre qué hacer. #xpost