• Nice syntax (mostly just that blocks/procs are easy to
use— Ruby-like syntax is nice, but it’s not really that important)
• straight-forward class/object model
• type system is simple but powerful (union types + type inference are a great combo)
• syntax and std lib that enables functional-style
programming, but isn’t strictly functional
• Pretty darn fast— compiles to machine code via
LLVM, and seems like it’s not far behind C, C++
and Rust in most benchmarks, despite being
garbage collected
Julia ticks all those boxes except the "straightforward class/object model" (which I initially missed). I should have been more clear that Julia takes a different route to Object Orientation (multiple dispatch instead of classes).While julia has a very different user experience for the reasons you mention, that doesn't seem to be what the OP was talking about, but maybe I'm wrong.
I think your original comment was fair. I've looked at Crystal and Julia and find both projects really exciting. That said, it's hard to see why one would prefer Crystal's class/object model to Julia's. Multimethods + operator overloading is just insanely powerful and elegant. It's one of Julia's real strengths and allows for a new level of code reuse.
I wish Julia had a more python-like syntax (I don't want to open a can of worms with this comment but do feel that Python's popularity is at least to some degree attributable to a aesthetically pleasing syntax.), and I wish its syntax were more regular (I'm sure the Mathematica function definition style will lead to problems with tooling, linters. C++, to my mind, shows the perils of an overly-complex syntax, and Julia, in a well-meaning attempt to entice scientists, risks doing the same.). But in every other sense Julia is just fucking awesome.
That said - Crystal is pretty cool too, and if you're a ruby programmer I'm sure it's a compelling language to use.
Would you elaborate on what's different about writing Julia?
If you define one method with the exact same parameters as an older one it will just redefine it. As a side-note, it has safe points where the JIT will work (usually the global namespace, in which the REPL runs each command), and otherwise it can't see newly declared methods (as it is running already compiled code) unless you use a method to force it (like invokelatest or eval). The period between safe-points is called the world age.