The Crystal Programming Language
crystal-lang.org
crystal-lang.org
Personally, I thought the muddled Proc, block, and lambda situation a mess, coming from Scheme 30 years ago to Ruby 20 years ago.
Why not use one (probably just block) for everything? Coming from ruby 10 years ago.
Scheme is a small language which achieves expressiveness by allowing you great freedom to push the language into bold new forms.
Ruby (especially with Rails which should almost be considered a separate language) is a big language where simplicity is maintained by informal convention.
Ruby has lots of muddles and messy features, good Ruby code bypasses them.
End
End
End
End
EndYou have the option to define named methods that yield or to use the short one-parameter syntax where this:
method do |param|
param.some_method
end
becomes method &.some_method1. Too slow to compile (the whole program + the entire stdlib is built everytime you build!). No incremental compilation available.
2. No language server (apparently it's just impossible due to the way the language works). Tbh, I'd be happy with just "Go to definition" but alas, no-can-do!
3. Obscure error messages (macros are to blame here)
4. Weak HTTP server implementation -- making things such as a fetching POST params or uploads incredibly frustrating. Once read the request body cannot be read again.
5. Weak/non-existent Windows support
6. No multicore support
7. Obviously small community
8. Nil handling takes a bit getting used to (coming from Ruby)
9. Error messages are hard to read with overloaded methods wherein just the types are used without any indication of what doesn't match
Overall, if the above changes, I'd switch to it in a heartbeat!
Emacs' dumb-jump appears to have some basic support for go to definition: https://github.com/jacktasia/dumb-jump/blob/master/dumb-jump...
But out of curiosity, what is the issue from a technical point of view?
This applies to the responsiveness and memory consumption of the language server as well as the regular compilation process. So this is an important topic, and we're working on improvements. It's a complex topic, but there are some ideas.
What most LSPs do is approximate it rather than worry about perfection and deliver nothing.
I feel like this is a bit strongly influenced by the macro experience. Macros are an advanced and powerful feature and naturally more complex to debug. In general, Crystal's error messages are often praised for their clarity and helpfulness (especially compared to dynamically typed languages, of course).
> 4. Weak HTTP server implementation -- making things such as a fetching POST params or uploads incredibly frustrating. Once read the request body cannot be read again.
The stdlib implementation of `HTTP::Server` is intentionally very bare-bones (many programming languages don't even have such a practically usable feature in stdlib). Specialized web server implementations are available as shards (https://shardbox.org/categories/Web_Frameworks). They're based on the foundation in stdlib and provide more advanced features.
> 5. Weak/non-existent Windows support
Windows support is pretty stable and almost complete by now.
> 6. No multicore support
Crystal has supported multi-threading as opt-in via the `-Dpreview_mt` flag. It's considered a preview, because it's to be used with care when dealing with data structures that are not thread-safe. But it has proven to work well in production use.
> 8. Nil handling takes a bit getting used to (coming from Ruby)
But once you're used to it, it's sooo much helpful. It just helps to avoid a lot of potential bugs which you would have to take extra care for in Ruby.
This isn't really a genuine statement. Currently Crystal Requires a full installation of Visual Studio on Windows:
> run `scoop install vs_2022_cpp_build_tools`
(from the "required libraries" link in https://crystal-lang.org/install/on_windows/)
https://github.com/neatorobito/scoop-crystal/blob/main/bucke...
no thank you.
But after the executable binary is compiled then it can run without any dependencies. I think the later is more important for a window program.
I gave the exes to my users and none of them had any problem running it.
For development currently WSL is still the best way to run crystal in windows.
WSL is never the best way to do anything, unless the question is "what is the best way to emulate Linux on Windows?". In all other cases, WSL is literally the worst way to do anything.
Alternatives: if you don't mind your eyes bleeding with C++-verbosity and tracking liveness yourself, there's Rust. Sure Go looks cute until you have a million users emailing you trivial questions they should've asked a group.
And if you want something similar to Crystal but with even stricter and more granular semantics than Rust with an even smaller community. there's Pony. It was built around the Orca GC. There's Nim too. Finally, one can use Haskell to built that critical payment service and maintain absolute job security. Meanwhile, the Erlang/Elixir OTP stack stays performant, although no one is quite sure how to package, deploy, and manage its lifecycle properly.
This works on Doom Emacs!
Crystal powers 90% of the Kagi search backend (reminder being Python). Highlights are great performance and concurency handling. Biggest downsides at this moment are compilation speed (does not take advantage of multi CPU cores) and debugging tools.
Overall our experience has been fantastic (we adopted it while still in beta) and the pace the language is developing is great.
Of course, no ads or trackers must help - when I look at the Network tab in developer tools the comparison with a google search is stark. ~4 requests vs. google's ~50.
Never would’ve expected it to be using Crystal though! That’s really neat. Are there open source bits? I’d love to see some enterprise-level Crystal examples
Tbh, I prefer it that way round than try to retrofit multi-core onto a model that wasn't designed for it. But yes, single-core feels a bit behind the curve in 2022.
Crystal's concurrency is based on fibers (green threads) which works very well even on a single thread (it scales to multiple threads, as well)
And for many use cases with high parallelization and little shared state (including web applications such as a search engine), multi-threading isn't necessary. Synchronization overhead is a serious performance killer. You can get much more performance out of running N processes with a single thread instead of a single process running N threads.
because a lot of beginners complain that Crystal's fiber doesn't work on multiple cores/multiple threads and then give up using it, it's probably not as important as people think.
Even many beginners mistakenly believe that the Crystal language does not support the creation of operating system native Thread, this is a huge misunderstanding for Crystal.
https://rillabs.com/posts/crystal-concurrency-easier-syntax-...
Crystal pretty much provides the same (great) concurrency functionality with light-weight threads and channels etc, but with a cleaner syntax and in my experience less gotchas around closing channels in the wrong place and order etc.
The main downsides compared to Go I've seen is:
- (As mentioned) Compile times
- Far less compelling cross-compilation story
p.s. hi Vlad :)
https://github.com/compumike/crystal-docker-quickstart
For example, you may do:
git clone https://github.com/compumike/crystal-docker-quickstart.git my_app
cd my_app
./d_dev
# docker container spins up in a few seconds... within the container's bash shell, try:
make spec
make && out/my_app
# outside container, you may edit src/main.cr, save it, and then again within container:
make && out/my_app
Good luck and enjoy! :)I've written about Crystal before and am using it in production... see https://news.ycombinator.com/item?id=32216786 and https://news.ycombinator.com/item?id=32081943
From my experience so far Crystal feels like a performant language with the wonderful feel of Python. Definitely check this language out if this is the first time you're hearing about it.
To celebrate that there is going to be a live event next Monday: https://forum.crystal-lang.org/t/10-years-of-crystal-celebra...
We're exploring the history and future of the language with past and current core contributors as well as industry guests.
Hopefully this will save you some time in manually creating the API clients in Crystal.
However it really needs a bit of “wow” factor to take off.
We’ve used it here and there in dribs and drabs but don’t see a reason to use it in a new project when there is Elixir and/or Rust.
Elixir brings the easy to use concurrency almost automatically. This and other features make it almost unbeatable for web and backend stuff.
Rust is just as fast as crystal. Albeit harder to grok.
Python was literally saved by the numerical libraries. Or there would not be real reason to keep using it.
I keep one weather eye open on crystal to see how it’s doing but have seen no real reason to start a new project with it as yet.
For me the syntax is not reason enough as yet. Elixir is maybe easier and functional to boot. Being object oriented in 2022 is not a good reason either.
I’m an old rubyist and I wish Crystal the best. I’ve been following it since it was a gleam in the eye, But … why? And for what??
Back when I joined Manas.Tech and learnt about Crystal, THE wow factor for me was the way `if` constraints optional types when you check it: https://crystal-lang.org/reference/1.5/syntax_and_semantics/...
That provides you the flexibility of having union types (variable may be `Thing1` or `Thing2`) for generic purposes, AND type-safetiness (is that a word?) when dealing with specific paths of your program that apply differently to some of the subtypes of the variable.
I think Swift and Kotlin support (some of?) that now. It was really new for me back in the day (around 2014?).
But that's from a coding point of view - not that much about niches, as you talk about.
By the way, how are we on data-science friendly IDEs? Debugging? Automatic thorough documentation generator? Tooling in general? Is the time to first plot fast?
Where I work, we desperately need a fast python.
ML and data engineering is a different story, of course. Also, I wouldn't be surprised if something clever could be done with a structural type system.
What’s wrong with casting variables to mutate their type?
There's some interesting things you can do with the type system too, like capturing dimensionality in the type: https://git.sr.ht/~kb/matrix/tree/main/item/src/matrix.cr
One missing item though is SIMD support: https://github.com/crystal-lang/crystal/issues/3057
Re docgen - that's built into the compiler: https://crystal-lang.org/reference/1.5/syntax_and_semantics/...
It sounds like Julia would be a better fit than Crystal?
Ironically they have similar problems: compile/start-up time (though crystal has working ahead of time compilation - AFAIK Julia developers are still working on speeding up "first run" in various ways).
Full multi tasking, POSIX compliant yadda-yadda actual OS written in Crystal. The author was also apparently in high school at the time.
As other said, it just needs a push and a few more important libraries. Really wishing that finally takes off.
The language is nice though. It seems like it would benefit from a bit more publicity.
Among the problems :
- A too long compilation. For 2 projects, the compilation in dev env takes more than 30 seconds for each compil, the developer experience is dead at this cadence.
- IDE integration: auto-completion, go to def, API docs, etc works when it wants (almost never).
- The community is too small which results in a lack of docs, examples, help. I spent days searching in Github projects, just to see examples of basic things.
- Instead of focusing on a main framework that makes everyone agree, everyone makes their own framework, their own libs (including me). The result is a lot of time and energy spent on duplicate packages and frameworks that are not necessarily maintained.
I continue to follow the evolution from afar, one day it may be possible to integrate Crystal in WASM, acceptable compile times, maybe a productive main framework :)
It's easy to write, and comparable in performance to Go and similar.
Rust, Zig, and Nim are solving different problems.
That being said, I'll grant that the distinction between "tiny runtime" and "no runtime" isn't useful and that C can be said to have a runtime insofar as most systems provide a `crt0` or equivalent.
It is fully deterministic, so it simply injects alloc/free calls in the generated code at compile time. It even has an option that can show you where the calls are injected.
https://nim-lang.org/blog/2020/10/15/introduction-to-arc-orc...
Tmk Crystal still lacks Windows support as well and probably other os's / archs's compared to Nim
https://crystal-lang.org/reference/1.4/syntax_and_semantics/...
Of course, same as Nim, you lose access to most of the stdlib.
In some applications memory allocation is not that important, so it's nice not having to think about it at all.
I've gone deep into Rust recently, but Crystal might still eat Python's lunch, a language I've fallen out of love with.
Nim is very close to Crystal. Some parts that might lead you to prefer Crystal however:
- Nim compiles to C code, meaning Nim is coupled to what C can do. I find compiling to C to be distasteful, C is not meant to be a compilation target. We should be getting away from C, IMO. Nim is limited to what C can achieve, and the design of the language trends towards "here's how this translates to C" as a result. Compiling to C is also an extra layer of abstraction, as now for instance with debugging you have to go through the C layer. Crystal like Rust uses LLVM
- Crystal also uses Ruby syntax, which many prefer. I have grown to dislike semantic whitespace such as how Python works, so this is a plus for me.
- Crystal has a garbage collector, period, and leans into that. Whereas Rust, Zig, and Nim want to give you complete control over memory, Crystal is more focused on being a better high-level programming language, competing with the likes of JVM/NET/Go/Ruby. This focus is likely Crystal's main edge. The only other single-executable opinionated GCed language is Go. Crystal's type system is much better than Go's. If Crystal can reduce compile times and capture some of Go's pragmatic aura, it will see more success.
I use Python for work because of the math/sci libraries and ecosystem, but would otherwise use a Ruby-inspired language.
This isn't about the language, but I was surprised to see that Nikola motors is a sponsor. Wasn't that company a fraudulent Hydrogen Fuel vehicle startup[1]? I wonder what the story is there- I find it hard to imagine anyone would be doing much software engineering at the company in the first place, even if it *were* working on the technologies they claimed to.
Just because the Pr0n industry overwhelmingly uses PHP does not mean People should not use PHP.
Bad people use good tools too.
I think you know the answer.
https://github.com/luckyframework/lucky
Development by folks come from thoughtbot.
I expect full WASM support in the near future.
https://crystal-lang.org/reference/1.5/syntax_and_semantics/...