Crystal is a Ruby-like programming language with the power of C. Ruby/Rails developers especially should try this language because of its similarity to Ruby in syntax and pure elegance. Crystal offers the performance and efficiency of C, which is mostly used to write low-level systems with ease.
In this article, we will discuss the following topics, along with a few basic things Crystal can offer:
Crystal was originally named Joy and began development in 2011. The first official version was released in 2014 and since then has been under constant development until March 2021, when Crystal 1.0 arrived.
Crystal is a statically typed systems programming language with several important developer-friendly goals. Inspired by Ruby, Crystal has a gentle learning curve that makes it easy to read and write. It also offers type checking at runtime but does not always require defining variable types or method arguments.
The team behind Crystal has made it clear that its similarity to Ruby is not the language’s raison d’être. While inspired by Ruby’s productivity, Crystal compiles to native code with the use of LLVM and uses type inference, which automatically concludes the type of an expression at compile time.
Concurrency in Crystal works similarly to Go in that it uses threads called “fibers” to communicate without having to share memory. This is different from parallelism; two code paths cannot be executed at the same time, but are dependent on the previous task’s completion before the next task can begin. Crystal fibers are similar to OS threads except that they are lightweight and are managed by the process internally.
Crystal also boasts the ability to call C code just by writing bindings to it, which gives us the ability to pass data between the two. This allows us to take advantage of the strengths of both languages.
The team also clarified that Crystal will be backwards-compatible with previous versions, meaning that while the built-in libraries are being updated, they will still work without an update. These built-in libraries are grouped into “shards” and dispensed using Git. A Shard is a package of Crystal code with built-in commands from its respective repository, available when you specify them through a YAML file.
Before Crystal 1.0, there had been prior releases that lacked the significant language and compile stability of the current version, which have made Crystal particularly useful. Future releases will include bug fixes and other maintenance and will be regarded as patch releases.
Crystal supports many different platforms, ranging from macOS to WindowsSubsystem for Linux. Crystal compiler is yet to run on Windows, but it is on the roadmap for future releases.
If you are using macOS, you can use Homebrew, which will help you install the latest version:
brew update brew install crystal
For WindowsSubsystem for Linux (Ubuntu and Debian), you can write the following:
curl -fsSL https://crystal-lang.org/install.sh | sudo bash
Contributing to Crystal means that you will have to install it from sources.
Our first program will be “Hello World” because it is a large, complex program (just kidding)! This is what a simple “Hello World” looks like in Crystal, and we will save it in a hello_world.cr
file:
puts "Hello World!"
puts
in the code above stands for “put string.” The entire program is mainly a call to the method puts
, which then outputs the "Hello World!"
.
We then run it like this:
$ crystal hello_world.cr Hello World!
The HTTP server code sample looks like this:
require "http/server" server = HTTP::Server.new do |context| context.response.content_type = "text/plain" context.response.print "Hello world! This is our server" end address = server.bind_tcp 3000 puts "Listening on http://#{address}" server.listen
This makes more sense if you become familiar with the language, but a few things we can take are:
require "http/server"
We use require
to require files, which hold the code we need:
address = server.bind_tcp 3000
The port is set using the method bind_tcp
. This method is from the object HTTP::Server
.
Assigning variables works like this:
name = "Victor!" age = 23 p! name p! age
p!
is similar to puts
, only that p!
prints the expression in code:
age # => 23
Reassigning a variable is a requirement:
age = 23 p! age age = 24 p! age
Similar to how control expressions work in other languages, Crystal uses the following:
name = "Victor!" age = 23 if age > 23 name = "Matt" elsif age < 23 name = "Mike" else name end
Logical and
and or
operators work with Crystal, too. The and
is if — and only if — the operands are true. The sample below is the same as the one in the documentation:
some_exp1 && some_exp2 # The above is the same as: tmp = some_exp1 if tmp some_exp2 else tmp end
Logical or
or ||
are syntactical sugar for if
:
some_exp1 || some_exp2 # The above is the same as: tmp = some_exp1 if tmp tmp else some_exp2 end
To define a method in Crystal, we use the keyword def
, followed by the method name. After the expression comes the end
keyword:
def greet puts "Hello Victor! It is nice to have you here" end greet()
Several methods can have the same definition but with different parameters. This is called method overloading, which improves the readability of the program:
def say_hello(arg : String) puts "You are #{arg}!" end def say_hello(age : Int32) puts "You are age" * age end say_hello "Victor" say_hello 23
Crystal also supports type reflections by providing methods such as typeof
, as
, as?
, responds_to
, nil
, and is_a?
.
Error handling in Crystal is done by raising and rescuing exceptions. This means that for every error encountered, you will need to raise an exception and handle it (or rescue
, in Crystal) by specifying a variable in the rescue clause or by simply outputting a message. It is much easier to understand if you read the code below:
begin raise "An Error!" rescue puts "We caught it for you boss!" end # Output: Rescued!
While specifying a variable in the rescue clause, you can now access the exception:
begin raise "An Error!" rescue ex puts ex.message end # Output: An Error!
raise
is a method with overloading, and it accepts String
and Exception
instances:
raise "An Error!" raise Exception.new("An Error!")
With contributions from more than 450 developers for v1.0, it is easy to see that Crystal is going to be well-loved in the future. The current release is all about language stability, which has set a high standard and made a huge step forward for the language.
There are currently 164 sponsors contributing to the sustenance of Crystal’s development. There have been 82 commits since version 0.36.1 made by 25 contributors; you can view the release changelog here.
The Crystal team still needs to make several adjustments, and I am hoping to see them in the subsequent maintenance releases. A roadmap has also been laid out for what still has to be done here.
Crystal’s documentation will also provide a better understanding of how things work, and be sure to check out their blog, where the team shares announcements and release notes.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.