Crystal 0.15.0 has been released!
This is a small release where the most significant change is that now !
and nil?
have their meaning hardcoded in the language. To understand why this is important let’s look at a simple example.
nil? and !
The task is to write a program that prints the character number of an occurrence of a string inside another string, or print “Not found” if not found.
One way to solve this is:
# `String#index` returns an Int32 if the index is found, or Nil if not
index = "some_word".index(ARGV[0])
if index
puts "Found at character number #{index + 1}"
else
puts "Not found"
end
Note that in the above program the first character, for the user, is 1, the second is 2, etc. That’s why we need to add 1 to the index.
The compiler understands that if index
is truthy (not nil
nor false
nor a null pointer)
then inside the then
branch index
can only be Int32
so the operation index + 1
compiles fine.
Another way to write the same program is this:
index = "some_word".index(ARGV[0])
if !index
puts "Not found"
else
puts "Found at character number #{index + 1}"
end
If you compile the above program in a previous version you will get an error:
Error in ./file.cr:14: undefined method '+' for Nil (compile-time type is Int32?) puts "Found at character number #{index + 1}" ^
In this case it would seem obvious that in the else
branch there’s no possible
way index
can be nil
. However, because !
was a regular method and anyone could
redefine its meaning, the compiler couldn’t make this guarantee.
Now !
has its meaning hardcoded, which means that the last program compiles just fine.
Yet another way to write the same program is this:
index = "some_word".index(ARGV[0])
if index.nil?
puts "Not found"
else
puts "Found at character number #{index + 1}"
end
As before, if you compile this with a previous version you will get the same error,
for the same reason: you could redefine the meaning of nil?
.
Starting from 0.15.0 nil?
has its meaning hardcoded, so the above program again works
just fine.
This is super important because now the language is much more intuitive and correct.
And there are many Ruby programmers that use nil?
, a lot, and if they start using
Crystal there won’t be any surprises in their expectations about what the compiler should
understand in these cases.
Some others ways to write this program:
# 1
if !index.nil?
puts "Found at character number #{index + 1}"
else
puts "Not found"
end
# 2
if index.is_a?(Int32)
puts "Found at character number #{index + 1}"
else
puts "Not found"
end
# 3
if !index.is_a?(Int32)
puts "Not found"
else
puts "Found at character number #{index + 1}"
end
All of the above will now work just fine, as one would expect.
We originally considered removing nil?
from the standard library and language, but Nil
is such a fundamental type that it makes sense to have good support for handling it.
And remember: nil
is not a billion dollar mistake
if the compiler takes care of making sure you always handle it.
Better Playground
The playground (crystal play
)
had many bug fixes, stablizations and improvements. For example runtime exceptions are now pointed
out in the source code.
There’s also a new “Workbook” tab/section that can list files you put in a playground
directory,
to use it as a tutorial for others, or maybe when giving a talk. These files can be HTML,
Markdown or Crystal files.
For example, @will gave a talk about Crystal a few days ago at Ruby on Ales and used it to introduce the language. Make sure to check out his repo and try it out.