Crystal 0.20.0 has been released!
Aside from the usual bugfixes and some performance improvements there’s a lot of new stuff here.
Shards 0.7.0
Crystal 0.20.0 comes with version 0.7.0 of shards,
mostly maintained by Julien Portalier,
whichs has a few new goodies like a build
command and informational
crystal
(version) and libraries
entries in the shard.yml
file.
Support for GitLab dependencies was also added.
Line and file number information in backtraces
Julien Portalier also added
line and file number information to exception backtraces
when programs are compiled with -d
or --debug
.
For example:
# example.cr
def foo
bar
end
def bar
raise "OH NO!"
end
foo
Compiling and running:
$ crystal build example.cr -d $ dsymutil --flat example # only needed on Mac OSX $ ./example OH NO! (Exception) 0x434f00: *bar:NoReturn at /opt/crystal/example.cr 8:3 0x434ee6: ??? at /opt/crystal/example.cr 4:3 0x431273: ??? at /opt/crystal/example.cr 11:1 0x434da9: main at /root/.cache/crystal/macro93695696.cr 12:15 0x7f9c98798f45: __libc_start_main at ?? 0x430c29: ??? at ?? 0x0: ??? at ??
File, line and column numbers appear on the right side. There’s still some things to improve here, but this is definitely and improvement and now it’s so much easier to trace an exception back to the source code.
ARM and AArch64 support
Julien Portalier is also the one who added support for these platforms.
LLVM 3.9 support
By… guess who? Julien Portalier once again! If we had something like “Crystal Awards”, well, now we know who would get the first place prize, right? ;-)
HTTP client and server streaming
Before 0.20.0 an HTTP::Server
handler would receive a request with its
entire body already loaded in memory. This wasn’t optimal, as maybe the
body is needed, or it needs to be streamed. 0.20.0 introduces this (breaking)
change. So, for example, one can stream a request directly into a JSON-mapped
object, thus avoiding many intermediate memory allocations. For example:
require "http/server"
require "json"
class Point
JSON.mapping x: Float64, y: Float64
end
# Accepts a JSON object representing a point and
# returns its absolute value (distance)
server = HTTP::Server.new(4567) do |context|
request, response = context.request, context.response
body = request.body
if body
point = Point.from_json(body)
abs = Math.sqrt(point.x ** 2 + point.y ** 2)
response.content_type = "application/json"
{abs: abs}.to_json(response)
else
response.status_code = 400 # bad request
response.content_type = "text/plain"
response.puts "Missing body"
end
end
puts "Listening on port 4567"
server.listen
And then:
$ curl localhost:4567 -XPOST --data '{"x": 3, "y": 4}' {"abs":5.0}
Also, an IO
can be passed into an HTTP::Client
when perfoming a POST or PUT,
so you can now upload a file very easily:
require "http/client"
response = File.open("some_file.txt") do |file|
HTTP::Client.post("http://example.com", body: file)
end
Unicode aware methods for String and Char
Methods like String#downcase
and String#upcase
are now unicode aware.
Where previously a program behaved like this:
"RubyConf 2016 at São Paulo was awesome!".upcase
# => "RUBYCONF 2016 AT SãO PAULO WAS AWESOME!"
(notice the small ‘ã’)
Now it behaves correctly:
"RubyConf 2016 at São Paulo was awesome!".upcase
# => "RUBYCONF 2016 AT SÃO PAULO WAS AWESOME!"
This of course works for any language, and even some complex ligatures are handled:
"ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЁЯЧСМИТЬБЮ".downcase
# => "йцукенгшщзхъфывапролджэёячсмитьбю"
"baffle".upcase # => "BAFFLE"
(The last example has ‘ffl’, which is a single character, but expands to three when upcased)
And even turkic is supported, where uppercase “i” is “İ” (an “I” with a dot):
"aeıiou".upcase(Unicode::CaseOptions::Turkic)
# => "AEIİOU"
Random enhancements
These are not random enhancements, but rather enhancements to the Random module. Specifically, the ability to generate random integers of any type and any range, without overflow issues.
rand(Int64::MIN..Int64::MAX) # => 4544345849288905241
Thank you Oleh Prypin for another excellent contribution!
Optimized Array#sort
Tatsujin Chin sent a PR that
replaces the old quicksort implementation with an
introsort one.
The end result is that this is now not only faster than the
old implementation, but also
faster than implementations in other languages,
like c’s qsort
and c++’s std::sort
. Super thank you,
Tatsujin Chin!
API docs have a nicer style
The style improvements include font changes and layout fixes. Take a look!
Special handling of common comments like TODO, OPTIMIZE and DEPRECATED was also added, and is now shown highlighted. Thank you Sam Eaton!
And more…
Make sure to read the full changelog for all the details, and upgrade instruccions due to some breaking changes.
We’d also like to thank everyone else that made this release possible with their contributions, reviews and suggestions.