# Know Ruby? Enter Crystal!

[Crystal](http://crystal-lang.org/) programming language is super interesting. I've spent the time checking out Crystal and digging through what is available, and wrote it all down as I learned.

#### Frequently Asked Questions

**Who are you?**

I'm [**Serdar Dogruyol**](https://github.com/sdogruyol), and I've been a Crystalist for years now. I'm the author of [Kemal](http://kemalcr.com/), curator of [Crystal Weekly](http://www.crystalweekly.com/) and a [Crystal Core Member](https://github.com/orgs/crystal-lang/people).

I love new programming languages, and while I've been using Ruby for the past years, I've coded in Java, PHP, Crystal, Elixir and a host of others. I also love writing, and good documentation, which is hard to find. Crystal doesn't have a lot of that yet, so I'm pitching in!

**Why Crystal?**

I've written [a blog post](http://serdardogruyol.com/why-crystal) dedicated to this, but basically, Crystal is good at everything Ruby is not good at...plus as a Rubyist you already know some Crystal.

**What am I getting?**

Basically, you can read the whole thing online for free!

**Do I have to know Ruby?**

Really, I love alliteration: the only thing the **'for Rubyists'** really means is that I assume you don't know about types, pointers, concurrency, or similar things. That's okay, you've never had to think about them before! I explain this stuff in extra depth. If you program in another dynamically typed language, you'll be just fine. If you program in another typed language, you'll be more than fine.

**Where can I find some Crystal Libraries (Shards)?**

* [awesome-crystal](https://github.com/veelenga/awesome-crystal) has a curated list of Crystal shards.
* [crystalshards.org](https://crystalshards.org/) lists all of the available Crystal shards on GitHub (similar to rubygems.org)
* [Here is a list of some popular Ruby gems that have been ported to Crystal](https://github.com/crystal-lang/crystal/wiki/Crystal-Shards-for-Ruby-Gems).


# Chapter 1: Why Crystal?

You already write software in Ruby. It pays your bills. You enjoy it. Why should you care about Crystal?

Let’s think about Ruby for a minute: what’s its biggest weakness? For me, it’s these things:

* Concurrency
* Speed
* Documentation

What’s awesome about Ruby?

* Blocks
* Vaguely functional
* Syntax is pretty easy
* Focus on developer happiness
* Get up and running quickly
* Dynamically typed

So we could learn a lot from a language that’s easy as Ruby, handles concurrency well, and is fast. We don’t want to sacrifice anonymous functions, pretty syntax, or not making `AbstractFactoryFactoryImpls` just to get work done.

I think that language is *Crystal*.

Now: Crystal is not perfect. It is getting better. But the point is to *learn*. and using a language that’s very familiar, yet very different, can teach us a lot.

Here’s “Hello World” in Crystal:

```ruby
puts "Hello, world!"
```

Here’s a concurrent “Hello World” in Crystal:

```ruby
channel = Channel(String).new

10.times do
  spawn {
    channel.send "Hello?"
  }
  puts channel.receive
end
```

Here’s a rough port to Ruby:

```ruby
10.times.map do
  Thread.new do
    puts "Hello?"
  end
end.each(&:join)
```

That’s it. Note the stuff that’s *similar* to Ruby:

* Pretty same syntax.
* Variables, while statically typed, have inference, so we don’t need to declare types

Here’s some stuff that’s *different*:

* Being compiled and statically typed the compiler will yell at us if we mess up.

Oh, and:

```
$ time ./hello
./hello  0.00s user 0.00s system 73% cpu 0.008 total

$ time ruby hello.rb
ruby hello.rb  0.03s user 0.01s system 94% cpu 0.038 total
```

Five times faster. Yay irrelevant microbenchmarks!

Anyway, I hope you get my point: There’s lots of things about Crystal that make it syntactically vaguely similar enough to Ruby that you can feel at home. And its strengths are some of Ruby’s greatest weaknesses. That’s why I think you can learn a lot from playing with Crystal, even if you don’t do it as your day job.


# Chapter 2: Installing Crystal

### Binary installers <a href="#binary-installers" id="binary-installers"></a>

The Crystal project provides official binary installers. You can get both releases and nightlies. Binary installers are the fastest and easiest way to get going with Crystal. Because Crystal is written in Crystal, compiling the Crystal compiler actually entails compiling it three times! This means it’s quite slow. But a binary install should be snappy!

Crystal has a [lovely installation page](https://crystal-lang.org/install), so I recommend you just go check that out and download the proper version.

Note that this book has been tested with Crystal 1.5.0, and so if you use the latest nightly, something may have changed.

### From Source <a href="#from-source" id="from-source"></a>

You will probably build the nightly version if you build from source, so be ready for some bugs in the code samples. This book was written for 1.5.0.

The [Crystal README](https://crystal-lang.org/install/from_sources/) has great instructions for building from source. Just got follow their instructions!

#### Future Proofing <a href="#future-proofing" id="future-proofing"></a>

The version this book is written for is 1.5.0

If you run

```
$ crystal
```

and it spits out a bunch of help information, you’re good to go with Crystal.


# Chapter 3: Writing Your First Crystal Program

## Writing Your First Crystal Program  <a href="#writing-your-first-crystal-program" id="writing-your-first-crystal-program"></a>

Okay! Let’s get down to it: in order to call yourself an “X Programmer,” you must write “Hello, world” in X. So let’s do it. Open up a text file: I’ll use `vim` because I’m that kind of guy, but use whatever you want. Crystal programs end in `.cr`:

```
$ vim hello.cr
```

Put this in it:

```ruby
puts "Hello World!"
```

And run it with `crystal` command:

```
$ crystal hello.cr
Hello World!
```

It should run and print the output without error. If you get one, double check that you have the double quotation marks. Errors look like this:

```
$ crystal hello.cr
Syntax error in ./hello.cr:1: unterminated char literal, use double quotes for strings

puts 'Hello World!'
```

By the way `crystal` command is great for quickly running your code but it’s slow. Each time it compiles and runs your program Let’s see how much does it takes to run that program.

```
$ time crystal hello.cr
crystal hello.cr  0.30s user 0.20s system 154% cpu 0.326 total
```

0.326 seconds for a `Hello World`? Now that’s slow.

Instead of compiling and running again you can compile it to native code with the `build`command.

```
$ crystal build hello.cr
```

And to run your program, do the Usual UNIX Thing:

```
$ time ./hello
./hello  0.00s user 0.00s system 87% cpu 0.006 total
```

You should see “Hello, world.” print to the screen 50x faster :) Congrats!


# Chapter 4: Creating a new project

Up until now we’ve used the `crystal` command to only run our code.

Actually `crystal` command is pretty useful and does lot more than that. (check `crystal --help`for more)

For example we can use it to create a new Crystal project.

```
$ crystal init app sample
  create  sample/.gitignore
  create  sample/.editorconfig
  create  sample/LICENSE
  create  sample/README.md
  create  sample/shard.yml
  create  sample/src/sample.cr
  create  sample/spec/spec_helper.cr
  create  sample/spec/sample_spec.cr
Initialized empty Git repository in /Users/serdar/crystal_for_rubyists/code/04/sample/.git/
```

Awesome. `crystal` helped us create a new project. Let’s see what it did for us.

* Created a new folder named sample
* Created a LICENSE
* Created `shard.yml` for dependency management.
* Initialized an empty Git repository
* Created a README for our project
* Created `src` and `spec` folders to put our code and tests(ssh..we’ll talk about it soon) in it.

Let’s run it.

```
$ cd sample
$ crystal src/sample.cr
```

Nothing! Yay :)

Now that we create our first project. Let’s use some external libraries.

## Using Shards for dependency management <a href="#using-shards-for-dependency-management" id="using-shards-for-dependency-management"></a>

To manage dependencies of a project we use `shards`. `shards` is like `bundler` and `shard.yml` is like `Gemfile`.

* [awesome-crystal](https://github.com/veelenga/awesome-crystal) has a curated list of Crystal shards.
* [crystalshards.org](https://crystalshards.org/) lists all of the available Crystal shards on GitHub (similar to rubygems.org)
* [Here is a list of some popular Ruby gems that have been ported to Crystal](https://github.com/crystal-lang/crystal/wiki/Crystal-Shards-for-Ruby-Gems).

Let’s open up `shard.yml`.

```
name: sample
version: 0.1.0

authors:
  - sdogruyol <dogruyolserdar@gmail.com>

targets:
  sample:
    main: src/sample.cr

crystal: 1.5.0

license: MIT
```

This is a default `shard.yml` and it contains the minimal necessary information about our project. Those are

* `name` specifies the name of the project
* `version` specifies the version of the project. Crystal itself uses [semver](http://semver.org/) for version management so it’s a good convention for you to follow.
* `authors` section specifies the authors of the project. By default this is taken from your global `git` configuration.
* `crystal` specifies the version of Crystal that the project is using.
* `license` specifies the type of your project license. By default this is `MIT`.

Okay. That’s great but what can we do with this `shard.yml`? Well we can use this file to add external libraries(we call it dependency) and manage them without even worrying about any folders / paths e.g.. Sweet isn’t it?

Now that we know the true power of `shards` let’s add [Kemal](https://github.com/kemalcr/kemal) to our `shard.yml` and build a simple web application :)

Open up `shard.yml`. First we need to add `Kemal` as a dependency to our project. We do this by including

```
dependencies:
  kemal:
    github: kemalcr/kemal
    version: 1.2.0
```

That’s great! Now we added `Kemal` to our project. First, we need to install it.

```
$ shards install
Resolving dependencies
Fetching https://github.com/kemalcr/kemal.git
Fetching https://github.com/luislavena/radix.git
Fetching https://github.com/crystal-loot/exception_page.git
Fetching https://github.com/sija/backtracer.cr.git
Installing radix (0.4.1)
Installing backtracer (1.2.1)
Installing exception_page (0.2.2)
Installing kemal (1.2.0)
Writing shard.lock
```

Okay now we are ready to use `Kemal` in our project. Open up `src/sample.cr`

```ruby
require "kemal"

module Sample

  get "/" do
    "Hello World!"
  end

end

Kemal.run
```

Look how we used `require` to access `Kemal` in our program.

Let’s run.

```
$ crystal src/sample.cr
[development] Kemal is ready to lead at http://0.0.0.0:3000
```

Go to `localhost:3000` and see it in action!

Now you know how to add dependencies and use others’ `shard`s :)


# Chapter 5: Testing

Rubyists love testing, so before we go any farther, let’s talk about testing. In Crystal, there is a testing framework built in, and it’s named `spec`. It’s pretty similar to `RSpec`.

Let’s continue with the project we created in Chapter 04.

As you remember `crystal` created this project structure for us.

```
$ cd sample && tree
-- LICENSE
-- README.md
-- shard.yml
-- spec
  -- sample_spec.cr
  -- spec_helper.cr
-- src
  -- sample.cr
```

Did you see that `spec` folder? Yes, as you guess Crystal created this folder and the first spec for us. In Crystal a file is tested with corresponding `_spec` file. Since we named our project as `sample`it created a file named `sample.cr` and the corresponding spec with `spec/sample_spec.cr`.

By the way, in this context `spec` and `unit test` means the same so we can use them interchangeably.

Without further ado lets open up `spec/sample_spec.cr`

```ruby
require "./spec_helper"

describe Sample do
  # TODO: Write tests

  it "works" do
    false.should eq(true)
  end
end
```

Now this file is pretty interesting. There a three important keywords, `describe`, `it` and `should`.

Those keywords are only used in `spec`s with the following purposes.

* `describe` lets you group related specs.
* `it` is used for defining a spec with the given title in between “”.
* `should` is used for making assumptions about the spec.

As you can see this file has a group `describe`d as `Sample` and `it` has one spec with the title of `works` which makes the assumption that false `should` equal true.

You might be asking ‘How do we run these tests?’. Well `crystal` command to the rescue.

```ruby
$ KEMAL_ENV=test crystal spec
F

Failures:

  1) Sample works
     Failure/Error: false.should eq(true)

       Expected: true
            got: false

     # spec/sample_spec.cr:7

Finished in 420 microseconds
1 examples, 1 failures, 0 errors, 0 pending

Failed examples:

crystal spec spec/sample_spec.cr:6 # Sample works
```

Yay! We got a failing(red) test. Reading the output we can easily find which spec failed. Here it’s the spec within the group of `Sample` titled `works` a.k.a `Sample works`. Let’s make it pass(green).

```ruby
require "./spec_helper"

describe Sample do
  # TODO: Write tests

  it "works" do
    true.should eq(true)
  end
end
```

Rerun the specs.

```ruby
$ KEMAL_ENV=test crystal spec

.

Finished in 383 microseconds
1 examples, 0 failures, 0 errors, 0 pending
```

Green! That’s all you need to know to get started. Next up: FizzBuzz.


# Chapter 6: FizzBuzz

Of course, the first thing that your job interview for that cushy new Crystal job will task you with is building FizzBuzz. Let’s do it!

If you’re not familiar, FizzBuzz is a simple programming problem:

> “Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.”

This will give us a good excuse to go over some basics of Crystal: Looping, tests, printing to standard output, and a host of other simple things.

First, let’s create our project.

```
$ crystal init app fizzbuzz
```

Let’s write our first failing test. Open up `/spec/fizzbuzz_spec.cr`

```ruby
require "./spec_helper"

describe Fizzbuzz do
  it "shouldn't divide 1 by 3" do
    div_by_three(1).should eq(false)
  end
end
```

And run it:

```
$ crystal spec
Error in ./spec/fizzbuzz_spec.cr:7: undefined method 'div_by_three'

div_by_three(1).should eq(false)
```

This makes sense: We haven’t defined any method yet. Let’s define one:

```ruby
require "./fizzbuzz/*"

def div_by_three(n)
  false
end
```

Akin to Ruby, the value of the last expression gets returned.

TDD means do the simplest thing! Now that we’ve defined our method, let’s compile and run our tests:

```
$  crystal spec
.

Finished in 0.82 milliseconds
1 examples, 0 failures, 0 errors, 0 pending
```

Awesome! We pass! Let’s write another test, and see what happens:

```ruby
require "./spec_helper"

describe Fizzbuzz do
  it "shouldn't divide 1 by 3" do
    div_by_three(1).should eq(false)
  end

  it "should divide 3 by 3" do
    div_by_three(3).should eq(true)
  end
end
```

Run it!

```ruby
$ crystal spec

.F

Failures:

  1) Fizzbuzz should divide 3 by 3
     Failure/Error: div_by_three(3).should eq(true)

       expected: true
            got: false

     # spec/fizzbuzz_spec.cr:9

Finished in 0.83 milliseconds
2 examples, 1 failures, 0 errors, 0 pending

Failed examples:

crystal spec ./spec/fizzbuzz_spec.cr:8 # Fizzbuzz should divide 3 by 3
```

We have 1 failure. Let’s make this pass.

```ruby
require "./fizzbuzz/*"

def div_by_three(n)
  if n % 3 == 0
    true
  else
    false
  end
end
```

Run it.

```ruby
$ crystal spec

..

Finished in 0.61 milliseconds
2 examples, 0 failures, 0 errors, 0 pending
```

Awesome! This shows off how `else` work, as well. It’s probably what you expected. Go ahead and try to refactor this into a one-liner.

Done? How’d you do? Here’s mine:

```ruby
def div_by_three(n)
  n % 3 == 0
end
```

Remember, the value of the last expression gets returned.

Okay, now try to TDD out the `div_by_five` and `div_by_fifteen` methods. They should work the same way, but this will let you get practice actually writing it out. Once you see this, you’re ready to advance:

```
$ crystal spec -v

Fizzbuzz
  shouldn't divide 1 by 3
  should divide 3 by 3
  shouldn't divide 8 by 5
  should divide 5 by 5
  shouldn't divide 13 by 15
  should divide 15 by 15

Finished in 0.61 milliseconds
6 examples, 0 failures, 0 errors, 0 pending
```

Okay! Let’s talk about the main program now. We’ve got the tools to build FizzBuzz, let’s make it work. First thing we need to do is print out all the numbers from one to 100. It’s easy!

```ruby
100.times do |num|
  puts num
end
```

Step one: print **something** 100 times. If you run this via `crystal build src/fizzbuzz.cr && ./fizzbuzz` you should see `num` printed 100 times. Note that our tests didn’t actually run. Not only are they not run, they’re actually not even in the executable:

Now we can put the two together:

```ruby
100.times do |num|
  answer = ""

  if div_by_fifteen num
    answer = "FizzBuzz"
  elsif div_by_three num
    answer = "Fizz"
  elsif div_by_five num
    answer = "Buzz"
  else
    answer = num
  end

  puts answer
end
```

Because the `if` returns a value, we could also do something like this:

```ruby
(1..100).each do |num|
  answer = if div_by_fifteen num
    "FizzBuzz"
  elsif div_by_three num
    "Fizz"
  elsif div_by_five num
    "Buzz"
  else
    num
  end

  puts answer
end
```

Notice that we also changed `100.times` to `(1..100).each`, to make `num` go from 1 to 100 instead of from 0 to 99.

Try running it.

Awesome! We’ve conquered FizzBuzz.


# Chapter 7: Types and Method Overloading

Crystal is like Ruby, but it’s not Ruby!

Unlike Ruby, Crystal is a statically typed and compiled language. Most of the time you don’t have to specify the types and the compiler is smart enough to do `type inference`.

So why do we need types? Let’s start with something simple.

```ruby
def add(x, y)
  x + y
end

add 3, 5 # 8
```

This is the same in Ruby! We just defined a method that adds two numbers. What if we try to add a number to a string?

```ruby
add 3, "Serdar"
```

First let’s do that in Ruby.

```
types.cr:2:in `+': String can't be coerced into Fixnum (TypeError)
    from types.cr:2:in `add'
    from types.cr:5:in `<main>'
```

What??? We just got a `TypeError` but we don’t have to care about types in Ruby ( or not :)). This is also a `runtime error` meaning that your program just crashed at runtime (definitely not good).

Now let’s do the same in Crystal.

```
Error in ./types.cr:5: instantiating 'add(Int32, String)'

add 3, "Serdar"
^~~

in ./types.cr:2: no overload matches 'Int32#+' with types String
Overloads are:
- Int32#+(other : Int8)
- Int32#+(other : Int16)
- Int32#+(other : Int32)
- Int32#+(other : Int64)
- Int32#+(other : UInt8)
- Int32#+(other : UInt16)
- Int32#+(other : UInt32)
- Int32#+(other : UInt64)
- Int32#+(other : Float32)
- Int32#+(other : Float64)
- Int32#+()

x + y
  ^
```

Okay, that’s quite a scary output but actually it’s great. Our Crystal code didn’t compile and also told us that there’s no overload for `Int32#+` and showed us the possible overloads. This is a `compile time error` meaning that our code didn’t compile and we catch the error before running the program. Lovely!

Now let’s add some types and restrict that method to only accept `Number`s.

```ruby
def add(x : Number, y : Number)
  x + y
end

puts add 3, "Serdar"
```

Run it.

```ruby
Error in ./types.cr:5: no overload matches 'add' with types Int32, String
Overloads are:
- add(x : Number, y : Number)

puts add 3, "Serdar"
     ^~~
```

Awesome! Our program didn’t compile again. And this time with shorter and more accurate error output. We just used `type restriction` on `x` and `y`. We restricted them to be `Number` and Crystal is smart enough to stop us from using the method with a `String`.

## Method Overloading  <a href="#method-overloading" id="method-overloading"></a>

We just saw a lot of overloads. Let’s talk about `Method Overloading`.

Method overloading is having different methods with the same name and different number of arguments. They all have the same name but actually they are all different methods.

Let’s overload our `add` method and make it work with a String.

```ruby
def add(x : Number, y : Number)
  x + y
end

def add(x: Number, y: String)
  x.to_s + y
end

puts add 3, 5

puts add 3, "Serdar"
```

Let’s run it.

```
$ crystal types.cr
8
3Serdar
```

Now, that’s method overloading in action. It figured out that we are calling the method with a Number and String and called the appropriate method. You can define as many overload methods as you wish.


# Chapter 8: Concurrency and Channels

Did you remember Chapter 1? We did a concurrent Hello World!

Here’s a quick reminder.

```ruby
channel = Channel(String).new

10.times do
  spawn {
    channel.send "Hello?"
  }
  puts channel.receive
end
```

In Crystal we use the keyword `spawn` to make something work in the background without blocking the main execution.

To achieve this `spawn` creates a lightweight thread called `Fiber`. `Fiber`s are very cheap to create and you can easily create tens of thousands of `Fiber`s on a single core.

Okay, that’s really cool! We can use `spawn` to make stuff work in the background but how do we get something back from a `Fiber`.

Now that’s where `Channel`s come to play.

## Channel <a href="#channel" id="channel"></a>

As the name stands a `Channel` is a channel between a sender and the receiver. Therefore a `Channel` lets each other communicate with `send` and `receive` methods.

Let’s take a line by line look at our previous example.

```ruby
channel = Channel(String).new
```

We create a `Channel` with `Channel(String).new`. Note that we are creating a `Channel` which will `send` and `receive` messages with type of `String`.

```ruby
10.times do
  spawn {
    channel.send "Hello?"
  }
  puts channel.receive
end
```

Leaving the loop aside, we are sending a message to our channel inside `spawn`. You might ask ‘Why are we sending message in the background?’ Well, `send` is a blocking operation and if we do that in the main program we gonna block the program forever.

Consider this:

```ruby
channel = Channel(String).new
channel.send "Hello?" # This blocks the program execution
puts channel.receive
```

What’s the output of this program? Actually this program won’t ever finish because it gets blocked by `channel.send "Hello?"`. Now that we know why we use `spawn` to send a message let’s continue.

```ruby
spawn {
  channel.send "Hello?"
}
puts channel.receive
```

We just sent a message through our channel in the background with `spawn`. Then we receive it back with `channel.receive`. In this example the message is `Hello?` so this program prints `Hello?`and then finishes.


# Chapter 9: Macros and Metaprogramming

We love Ruby because of its’ dynamic nature and metaprogramming! Unlike Ruby, Crystal is a compiled language. That’s why there are some key differences.

* There’s no `eval`.
* There’s no `send`.

In Crystal we use `Macro`s to achieve this kind of behaviour and metaprogramming. You can think of `Macro`s as ‘Code that writes/modifies code’.

P.S: `Macro`s are expanded into code at compile-time.

Check this.

```ruby
macro define_method(name, content)
  def {{name}}
    {{content}}
  end
end

define_method foo, 1
# This generates:
#
#     def foo
#       1
#     end

foo # => 1
```

In the example we created a macro named `define_method` and we just called that macro like a normal method. That macro expanded into

```ruby
  def foo
    1
  end
```

Pretty cool! We got `eval` behaviour at compile-time.

Macros are really powerful but there’s one rule that you can’t break.

***A macro should expand into a valid Crystal program***


# Chapter 10: C Bindings

There are lots of useful C libraries out there. It’s important that we make use of them instead of rewriting every single of them.

In Crystal, It’s super easy to use existing C libraries with bindings. Even Crystal itself uses C libraries.

For example Crystal uses `libpcre` for it’s `Regex` implementation.

Like I said it’s super easy to write bindings for C. Crystal itself links to `libpcre` like this

```ruby
@[Link("pcre")]
lib LibPCRE
...
end
```

With just 3 lines of code you we’re linked to `libpcre` :) We use `lib` keyword to group functions and types that belong to a library. And it’s a good convetion to start with `Lib` for your C library declarations.

Next we bind to C functions with the `fun` keyword.

```ruby
@[Link("pcre")]
lib LibPCRE
  type Pcre = Void*
  fun compile = pcre_compile(pattern : UInt8*, options : Int, errptr : UInt8**, erroffset : Int*, tableptr : Void*) : Pcre
end
```

Here we binded to `libpcre`s compile function with the matching types. Now we can easily access this function in our Crystal code.

```ruby
LibPCRE.compile(..)
```


