For the past several months i have been writing Crystal code for a micro service system with the usual web toys. Over this time i have banged my head on issue plenty of times.
Yesterday i ran again into the enforced Type system. After hours and being a idiot, a simple solution was found. And yet, today when trying to make a more clean code… guess who came back to bit me in the behind. Yes, mr Type System again.
class Template
@template : String
@action : String
# @string_values : Hash(String, ?) = {} of String => ?
def initialize( @template : String, @action : String )
end
def setString(data_name : String, data : String)
@string_values[data_name] = data
end
def setGeneric(data_name : String, data )
@string_values[data_name] = data
end
def export( )
hash = {
"_option_" => { "template" => @template },
"_target_" => { @action => { "data" => @string_values } }
}
return hash
end
end
Take this code as a example ( just a example ). The moment you initialize a hash, your stuck with the type that are defined. Even worse is that at times, you do not even know what types can be available. For instance namedTuples from DB rows or different Tuple amounts etc… So this code will always trigger compiler errors, no matter how many combinations you try.
Something as simple in dynamic languages as feeding a mixed types, becomes a huge mess that requires way more knowledge the deeper you go into Crystal.
Being honest. Crystal its Generics are not generics. They are simply a redirected type inference system. You are still required to provide a type, be it on class creation, on output or … Crystal does not have a real generic that can truly bypass the Type Check or does a lazy type check on the provided data. Or override a hash type after creation.
The example above is just that. A Snapshot of a bigger issue. Over time i noticed that you end up constantly writing code, that involves dealing with the type system for very little gain. At times i know that the types are correct and yet, trying to push this information in arrays or hash or move it around becomes so much about the types. Arrrg
On other fronts:
IDE:
Even basic things like a IDE are a big issue. You like a Jetbrain product? Too bad because the only Crystal plugin is syntax + really bad performance issues. Try pasting …
@string_values : Hash(String, String) = {} of String => String
… and enjoy a 4 or 5 second lockup on the IDE. And another 2 or 3 seconds when you move your mouse over it. Or how a simply 200 line module can becomes so slow, that your waiting more on the IDE to responds whenever you press enter, then anything else.
When you get tired off fighting, maybe you think. “Well, its a Linux product, let try Linux”. Here you are installing Mx-Linux, Crystal, VSC and … basic syntax that works. Some code hints but that is about it. You really feel underwhelmed. Most of the Crystal plugins for IDEs are years old and barely supported. I assume most regular users here are VIM users and simply know most of the code from their heads ( ruby background? ). But as somebody coming from a different background, it has been less then stellar experience despite biting my teeth for months.
Compiler:
The compiler can also be a big annoyance. Especially the compile times. I am using Sentry + Parallel to auto build the services. This cuts down on wait times but your still constantly. Save … wait for the auto compile … finally check the result. Sentry cuts down the delay from manually triggering the compile job but it does nothing for the compile times.
Documentation:
A lot of documentation is … what i can described typical for a community project. As in lacking, especially the API side of things. Good for basic understanding the basic language but again, do more then a simple program and you start seeing a lot of missing functions.
Windows and other features:
Its damming to see issues on Github dating back to 2015 mentioning Windows or Multithread support. I am sure it will come one day but for something that Manas in the 2017 “not new year resolution” mentioned for a 2018 goal, it feels like only one guy is really trying to solve that issue. Was the money from the donations not supposed to go to those goals?
Let alone proper IDE support beyond syntax. Let alone expecting actually working IDEs on Windows ( as they are going to rely on Scry compiled to Windows or a Windows Crystal compiler ).
1.0
When i see changes like … HTTP::Multipart to MIME::Multipart, that make me think. Darn glad i am not using Multipart ( yet ) or else this will have broken my code on a Crystal update. Probably with a non-descriptive error because nobody seen fit to include any warning or even a version warning. 0.27.x => This future may be removed or moved in X version. Nowp … just a instant change.
Its one example of many where code can break without any build in warnings. If you want people to treat Crystal for a successful project, pulling this type of constant changes is simply not acceptable. Its a playground currently and that is not a good thing.
Future:
I like Crystal but the more i work in the language… For me it hurts giving up on months of work but to be honest … I rather work with PHP and get stuff done then constantly fighting the language, compile times and other issues. The latest Type issues are simply the last drips in the bucket.
So yes, it has been another day where i ended up at 04h at night trying to fight Crystal to do what I want, not what Crystal wants. And i am fed up and tired of it. I can rewrite this code that took me months probably in a few weeks in PHP and be done with it.
I may way more issue about for Crystal but i am tired and too darn sleepy. So here is my sleep deprived harsh opinion of Crystal. Its a bit of a mess, that might turn into something good. But for now i do not advice it for any big project unless you have the manpower and knowledge.