Chapter 8 - Advanced Features
Finally, my final chapter! This is an interesting one, I learned quite a bit from here, though I think each of the major features deserved its own chapter instead of a section.
So, advanced crystal here is comprised of-
- Macros
- Concurrency
- C-binding and
- Database Access
First, let’s check out Marco. I remember teaching Macro to a Django Developer colleague through Django templating language. It was very effectively communicated I believe. I was happy to see Crystal being much closed to the Django Template syntax than Clojure (my only macro example back then). It has {{}}
and {% for <loop> %}...{% end %}
. I think the chapter does great in explaning macros both in terms of what they are and how they are implemented in Crystal. method_missing
, inherited
, extended
and included
are hook-ish Macro-s that you can define to metaprogram on specific events (i.e. what happens when a method is missing? A subclass is defined? etc). I only tried out method_missing
on playground, rest will follow. But it does seem straight forward.
Next comes C binding. This too looks quite simple in Crystal (compared to any other language I used). I got introduced to “annotations”, “lib” and “fun” syntaxes! I don’t recall having seen them described earlier. Anyways, upon visual inspection- lib
is grouping of C libraries and fun
inside a lib is a signature by signature mapping of same named C functions (More new syntaxes: *
at the end for pointers that were introduced in this chapter). Annotations would map the C library with the following lib
block. After this setup is made, we’re pretty much back to Crystal-land calling the FUNctions.
However, upon inspecting the Crystal Docs, there seems to be a lot more in binding Crystal with C than it was mentioned in the book (though it is suggested to reach out to that link to know more). Examples include, unsafe, enums, threadlocals, callbacks and many more. I think C <> Crystal is a big selling point for Crystal and from whatever I have skimmed through (have not executed anything) I do seem to be impressed at the simplicity of it. I would have been a lot happier if there were an example that does more than just a C void greet(const* char)
function being called from Crystal, but something a little more. Perhaps the temperature converter mentioned in the first chapter? Or the Mineral system in the subsequent ones converted into struct
?
One other thing, this chapter mentions once- “C is a strongly typed language” where it should have been C is a statically typed language. “Strong” and “Weak” typing is rather relative in my opinion and also in my opinion, “Strongly Typed” is not really a strong suit of C-s, it’s rather on the “weaker” end when it comes to “strength” of typing. Again, very nit. Also, I got to learn of system
in Crystal which lets you execute an OS command (as does backticks, though not mentioned in the book).
Anyways, this book is not a reference and it DID do a great job of pointing me to the right direction after motivating me enough. Also, this chapter, particularly this section, had inspired me to continue playing with Crystal, so that too is a good thing.
After C-binding came concurrency. Crystal concurrency is like Go concurrency where go
is spawn
. You have channels, channels can be buffered, selected, yielded etc. The unit of concurrency is called Fiber. I think anyone understanding the conveyor belt metaphor and Go’s way of concurrency will find it easier to understand Crystal’s point of view. And in my opinion, Crystal does it with a much more beautiful syntax:
def generator(n : T) forall T
chan = Channel(T).new
spawn do
loop do
sleep n
chan.send n
end
end
chan
end
ch1 = generator(1)
ch2 = generator(1.5)
ch3 = generator(5)
loop do
select
when n1 = ch1.receive
puts "Int: #{n1}"
when f1 = ch2.receive
puts "Float: #{f1}"
when ch3.receive
break
end
end
^ Another example from the book.
Final section for this chapter was DB integration. The pattern is simple:
DB.open do |db|
db.query sql do |r|
<do your thing with `r`>
end
end
And that db
also has exec
, query_one
, query_all
etc. It only briefly mentioned Transactions at the end but looking at the design pattern, it’s simple to guess: db.transaction do |tx| ... end
, I verified my guessing from Crystal docs.
So this was the final chapter highlights from my side. I left one out (the one with web frameworks) but I will revisit it from a “meta” viewpoint if I look into a Crystal framework, but that will be my highlights on the framework, not the chapter, and it may happen much later. As far as chapter-by-chapter exploration is concerned, I am finished here
I could go on and on about how this book club journey has been for me (It was obviously good, I learned a language in ~40 posts!), but I will keep that for my upcoming post where I will summarize my experience, as for conclusion of this chapter/post, I will summarize my overall feelings of this chapter.
It was a “heavy” chapter, a lot of concepts to swallow in one unit. I wish this chapter was a PART
with at least three chapters- Advanced Syntax (Macro + Generics maybe?), C-Binding, and Concurrency. The chapter on Database could’ve been merged with the Web Frameworks chapters. However, it is my opinion based on my worldview of things and this really is not a bad thing of this book. This chapter did a great job by having me see all these things and occasionally try them out in one weekend evening. I understand those things are out there in the docs, but the book prepared and outlined all the things and placed it in the right sequence of the ToC and got me there, if I am ever to deal with a problem in Crystal that does any of these, I am prepared, the remainder of the execution is the reference docs and my effort’s job. Despite my nitpicks and complaints, I will give it 4/5, based on the benefits I received from reading it!
Yes, I will continue with Crystal, and possible this year’s Advent of Code will be divided between Crystal and OCaml for me