Crystal Introduction
by "Blag" - Senior Developer Evangelist
What is Crystal?
Syntax similar to Ruby.
Statically type-checked without need for type of variables or method arguments.
Can call C code using bindings.
Compiles to efficient native code.
How to install Crystal?
On Linux run this on the terminal
curl https://dist.crystal-lang.org/apt/setup.sh | sudo bash
Then simply do sudo apt-get install crystal.
On a Mac do brew install crystal-lang.
On Windows, do nothing because is not supported...
Who uses Crystal?
Even though Crystal is an alpha mode...there are companies using it in production
- Diploid - Human genome interpretation
- NeuraLegion - Machine Learning powered advance protocal fuzzer
- Neopoly GmbH - Online games and services
- Appmonit - Analytics engine
- Blitline - Online image processing
- Manas - Unconventional software for unconventional needs
Starting out...
Crystal doesn't come with a REPL...but it comes with a Web Playground!
Simply type crystal play
Open your browser and go to http://localhost:8080

Package Management
In order to get and use external libraries in Crystal we need to create a shard file by doing
shards init
Then adding the library information like this...
dependencies:
toml:
github: manastech/crystal-toml
branch: master
Basic Concepts
Printing on the screen is easy...
And only one line comments are allowed...
puts "This is Crystal!"
#This is a Crystal comment
Arrays are easy...
numArray = [1, 2, 3]
puts numArray
#[1, 2, 3]
strArray = %w(this is Crystal)
puts strArray
#["this", "is", "Crystal"]
Multidimension Arrays are easy too...
numArray = [[1, 2],[ 3, 4]]
puts numArray[0][1]
#1
puts numArray[1][1]
#3
Some fun with Arrays...
numArray = [1, 2, 3, 4]
numArray.push(5)
puts numArray # [1, 2, 3, 4, 5]
numArray.pop
puts numArray # [1, 2, 3, 4]
a = [1, 2]
b = [3, 4]
a.concat(b)
puts a # [1, 2, 3, 4]
puts numArray.first # 1
puts numArray.last # 4
numArray = [1, 2 ,3, 4]
puts numArray.shuffle() # [2, 3, 1, 4]
numArray.map! {|x| x * x}
puts numArray # [1, 4, 9, 16]
numArray.reverse!
puts numArray # [16, 9, 4, 1]
numArray = [[1, 2], [3, 4]] # [1, 2, 3, 4]
puts numArray.flatten
We can iterate on Arrays and Hashes...For doesn't exit
lang = ["Spanish","English","German"]
lang.each { |x| puts x }
#Spanish
#English
#German
lang = {"Spanish" => "Peru",
"English" => "US",
"German" => "Germany"}
lang.each_key{|x| puts "#{x} is spoken in #{lang[x]}"}
#Spanish is spoken in Peru
#English is spoken in US
#German is spoken in Germany
Functions
Functions always return the last value
def concat(a : String, b : String): String
a + " " + b
end
message = concat("Hello", "Crystal")
puts message # Hello Crystal
Although sometimes return is needed...
Classes
In Crystal, everything is an object
- It has a type
- It can respond to some methods
class Person
property age
def initialize(name : String)
@name = name
@age = 0
end
def name
@name
end
def age
@age
end
def become_older(by = 1)
@age += by
end
end
blag = Person.new "Blag"
blag.age = 40
puts blag.name # Blag
puts blag.age # 40
blag.become_older
puts blag.age # 41
blag.become_older 5
puts blag.age # 46
Fibonacci List
Finally...we're going to make our first application...
So grab your favorite text editor and get ready...
Name your file "fibonacci.cr"
def fib(num : Int32, a : Int32, b : Int32) : String
result = ""
if a > 0 && num > 1
result = result + " " + (a + b).to_s +
fib(num - 1, a + b, a)
elsif a == 0
result = a.to_s + " " + b.to_s + " " +
(a + b).to_s + fib(num - 1, a + b, b)
end
return result
end
print "Enter a number: "
num = gets.as(String).strip.to_i
puts(fib(num, 0, 1))
Open the Terminal and go to your source code folder...
crystal "Name_of_File.cr"
When we run it we're going to see...

Making an LED Number App
This is one of my favorite codes of all time...
Name your file "LED_Numbers.cr"
leds = {0 => [" _ ","| | ","|_| "],
1 => [" ","| ","| "],
2 => [" _ "," _| ","|_ "],
3 => ["_ ","_| ","_| "],
4 => [" ","|_| "," | "],
5 => [" _ ","|_ "," _| "],
6 => [" _ ","|_ ","|_| "],
7 => ["_ "," | "," | "],
8 => [" _ ","|_| ","|_| "],
9 => [" _ ","|_| "," _| "]}
print "Enter a number: "
num = gets.as(String).strip
i = 0
loop do
j = 0
loop do
print leds[num[j].to_i][i]
break if j == num.size - 1
j += 1
end
puts ""
break if i == 2
i += 1
end
When we run it we're going to see...

Random Names
This App will generate 100,000 random names using two 16 elements arrays
We will measure the runtime
Name your file "Random_Names.cr"
start = Time.now
names = ["Anne","Gigi","Blag","Juergen","Marek",
"Ingo","Lars","Julia", "Danielle","Rocky",
"Julien","Uwe","Myles","Mike","Steven",
"Fanny"]
last_names = ["Hardy","Read","Tejada","Schmerder",
"Kowalkiewicz","Sauerzapf","Karg",
"Satsuta","Keene","Ongkowidjojo",
"Vayssiere","Kylau","Fenlon",
"Flynn","Taylor","Tan"]
full_names = [] of String
i = 0
loop do
full_names.insert(0, names[Random.rand(16)] + " " +
last_names[Random.rand(16)])
break if i == 99999
i += 1
end
puts Time.now - start
When we run it we're going to see...

How this behaves in Python?

And what about Go?

Crystal was faster this time!
Decimal to Romans
This App will create a Roman Numeral based on a decimal number
This will include some nice commands...
Name your file "Decimal_to_Roman.cr"
Roman_Table = {1000=> "M", 900=> "CM", 500=> "D",
400=> "CD", 100=> "C", 90=> "XC",
50=> "L", 40=> "XL", 10=> "X",
9=> "IX", 5=> "V", 4=> "IV", 1=> "I"}
def roman_number(number : Int32): String
result = ""
while number > 0
Roman_Table.each_key{|x|
if number >= x
result += Roman_Table[x]
number -= x
break
end }
end
return result
end
print "Enter a number: "
num = gets.as(String).strip.to_i
puts roman_number(num)
When we run it we're going to see...

Count Letters
In this example we're going to read a file and count how many time a letter appears...
Call your file "count_letters.cr" (all in lowercase).
Create a file called "readme.txt" with the following text...
"This is a text file that we're going to read it using Crystal"
line = File.read("readme.txt").strip
counter = {} of String => Int32
line.each_char{|x|
if counter.has_key?(x.to_s)
counter[x.to_s] += 1
else
counter = counter.merge({x.to_s => 1})
end }
counter.each do |key, value|
puts "#{key} => #{value}"
end
When we run it we're going to see...

Going beyond...
Crystal has an amazing number of libraries and projects for a language that it not even beta...
We're going to take a look at a couple of this libraries...
Kemal - Web Framework
Kemal is a lighting fast, super simple framework written in Crystal
It's very similar to Ruby's Sinatra
Although according to Kemal's website...it's way faster than Sinatra

We're going to do things the Crystal way...
On the terminal type
crystal init app fibonacci
This will generate the folders and structure of the app...

Now we need to install "kemal"
Open the generated shard.yml
name: fibonacci
version: 0.1.0
authors:
- <a.tejada.galindo@sap.com>
targets:
fibonacci:
main: src/fibonacci.cr
crystal: 0.23.1
license: MIT
dependencies:
kemal:
github: kemalcr/kemal
Then run this (making sure your inside the fibonacci's folder)...
shards install
This will install the dependencies making your app ready to go...
Now open fibonacci.cr and copy the following code...
require "kemal"
def fib(num : Int32, a : Int32, b : Int32) : String
result = ""
if a > 0 && num > 1
result = result + " " + (a + b).to_s +
fib(num - 1, a + b, a)
elsif a == 0
result = a.to_s + " " + b.to_s + " " +
(a + b).to_s + fib(num - 1, a + b, b)
end
return result
end
get "/" do
render "views/index.ecr"
end
post "/getfibo" do |env|
num = env.params.body["num"]
result = fib(num.to_i, 0, 1)
render "views/getfibo.ecr"
end
Kemal.run
Create the "views" folder inside the fibonnaci folder...not inside the "src" folder...
Create two files one called "index.ecr" and the other one "getfibo.ecr"
<!doctype html>
<html>
<head>
<title>Fibonacci List</title>
</head>
<body>
<form action="getfibo" method="post">
<input name='num' placeholder='Enter a number' />
<input type="submit" value="Send">
</form>
</body>
</html>
<!doctype html>
<html>
<head>
<title>Fibonacci List</title>
</head>
<body>
<h3>The fibonacci sequence is: <%= result %></h3>
<a href="/">Go back<a/>
</body>
</html>
To run we simply need to do
crystal run src/fibonacci.cr
And then go to http://localhost:3000 on the browser...
2D fun with CrSFML
CrSFML is a binding for SFML (Simple and Fast Multimedia Library)
It allows us to create 2D games in a fast and easy way...

The installation request that you built SFML from the source so here are the Instructions
Then we need to compile the VoidCSFML by doing a cmake . && make && sudo make install
Just make sure the version correspond to the installed SFML
Finally create a shard.yml and pass the following...
dependencies:
crsfml:
github: oprypin/crsfml
version: 2.4.10
Make sure you run shards install
If there's a complaint about not founding a library...simply run
ldconfig
require "crsfml"
window = SF::RenderWindow.new(SF::VideoMode.new(538,
300), "Nyan Cat!")
left_right = 0
up_down = 50
clock = SF::Clock.new
while window.open?
while event = window.poll_event
if event.is_a? SF::Event::Closed
window.close
end
end
texture = SF::Texture.from_file("NyanCat.png")
texture.smooth = false
sprite = SF::Sprite.new(texture)
sprite.position = SF.vector2(left_right, up_down)
if SF::Keyboard.key_pressed?(SF::Keyboard::Escape)
window.close();
elsif SF::Keyboard.key_pressed?(SF::Keyboard::Left)
if left_right > 0
left_right -= 1
end
elsif SF::Keyboard.key_pressed?(SF::Keyboard::Right)
if left_right < 400
left_right += 1
end
elsif SF::Keyboard.key_pressed?(SF::Keyboard::Up)
if up_down > 0
up_down -= 1
end
elsif SF::Keyboard.key_pressed?(SF::Keyboard::Down)
if up_down < 220
up_down += 1
end
end
window.clear(SF::Color.new(64,64,64, 255))
sprite.position = SF.vector2(left_right, up_down)
window.draw(sprite)
window.display
end
We can run this as a regular Crystal file...

We can move the cat up/down and left/right using the cursor keys
We can close the app by pressing "esc"
That's it for now
Crystal is an awesome and impressive language
Even thought is still in Alpha...
Anyway...there's a huge community and a ton of libraries and resources...
It wouldn't surprise me at all if more people start to favor Crystal over Ruby...
Contact Information
Blag --> a.tejada.galindo@sap.com
@Blag on Twitter