Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I wrote some Crystal recently for a hobby project. I have to say, I really like it.

• 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

What other languages offer a similar profile? D? Swift? Kotlin (via LLVM)?



> What other languages offer a similar profile? D? Swift? Kotlin (via LLVM)?

Julia. It’s fast, JIT compiled (static compilation is possible but it’s quite rough around the edges), has a fantastic type system, uses multiple dispatch to achieve some very cool stuff, has quite powerful lispy macros, and a really great community / library ecosystem, especially in scientific computing.


I'm an enthusiastic user of Julia, but I would not think of it as a language with a "similar profile" as Nim or Crystal. As you said, it's hard to produce static binaries, and they are huge if compared with Nim's or Crystal's. Moreover, the typical workflow for writing code is very different from what users of static languages follow (edit, compile, run, loop over).


The person I responded to specifically said the things they like about Crystal are:

    • 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 should have been more clear that Julia takes a different route to Object Orientation (multiple dispatch instead of classes).

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.


You're right, but I inferred there was more in the OP's list that this list of points. They mentioned D, Swift, and Kotlin Native (LLVM-based). The fact the OP excluded the JVM-based Kotlin (its best supported platform) made me think that an additionally implicit requirement was the production of a small stand-alone static executable, like D, Swift, Nim, and Crystal are able to do.


> Moreover, the typical workflow for writing code is very different from what users of static languages follow (edit, compile, run, loop over)

Would you elaborate on what's different about writing Julia?


Julia's typical workflow [1] is mainly REPL-based: you test ideas in the REPL, accumulate functions in modules and build larger payloads at the prompt (or in a Jupyter notebook, or using Juno [2] or VSCode). That's a sensible way of working for its main target: scientific computing and number-crunching tasks, where you must often explore and understand your data before betting able to implement real algorithms.

[1] https://docs.julialang.org/en/v1/manual/workflow-tips/

[2] https://junolab.org/


Hmm, that’s interesting - I enjoy REPL-based development, having spent a lot of time working in Python, and a little Clojure. How does the REPL experience play with the static typing (that I think) Julia has? If you change the type signature of a function in the REPL what happens?


Julia is a dynamic language, it doesn't have static typing. What happens is that it's dynamic nature is actually a superposition of all possible static implementations of a function. So if you call a * b with an integer it will JIT compile an integer based version of the product, while if you do it with matrices it will compile a matrix product version. Julia Base has 361 implementations of product, which any library or programmer can freely add at any point and the compiler will always match at compile time the most specific version defined for the combination of all arguments (multiple dispatch). You also usually don't need type hints when calling methods, the compiler will infer the types by itself and choose the optimal implementation.

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.


Julia is most comfortably used in the manner of a traditional Lisp: with a REPL open the entire time, sending snippets of code from your editor to the REPL for compilation, and then testing things out at the REPL. Sometimes people don't even write out a "main" function meant to be run from the outside world, but leave a few different entry point functions to be called from the REPL.


F#. I hate the syntax, but anyone who enjoys ML will like it. Curly braces are optional.

It also meets all of your other requirements, including the "isn't strictly functional" part (which is somewhat rare).

Scala has most of these qualities, but people say it's extremely complicated and supports too many different paradigms in a single language. I've never used it.


I'd second F# and also in the same vein recommend Ocaml, in particular, if fast-running native code is a requirement. I haven't benchmarked it enough but I suspect that in most cases Ocaml might be a good deal faster.

I'm also very sympathetic to the non-functional aspects. I think being able to write imperative code easily (and it's surprisingly pleasant in ocaml/f#) is a huge plus.


As always, take these numbers with a grain of salt, but benchmarks seem to suggest that F# on .NET Core is significantly faster than OCaml [1]. I wouldn't be surprised if that were the case myself given how much work Microsoft has put into optimizing .NET Core for performance.

[1] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...


And how much work Anthony Lloyd has put into optimizing those programs ;-)

https://benchmarksgame-team.pages.debian.net/benchmarksgame/...


> Curly braces are optional.

Why do languages make anything optional? It just leads to confusion and unnecessary style friction. I'm not saying everything should be as strict as Go, but... well, nothing should be optional.


In this case, I have no idea why they did it. Maybe to ease the transition from C-like languages to an ML language. I personally have never seen anyone use braces in F#.

Optional syntax is not at all rare, though.

Examples from various popular languages: white spaces, braces around single statements, trailing commas in lists, inferred type declarations, and parentheses.

There are also multiple ways to write things, like if...else vs. ternary operator vs. pattern matching vs. switch, often in the same language (C# has all of those, with pattern matching only being added recently due to demand).

I agree that I'd prefer that there only be one way to do things, but that's easier said than done. Sometimes users demand new syntax for different contexts or for the sake of terseness.


Does F# offers native builds ? I thought it was CLR only.

Also Scala is about to jump to a new compiler (and maybe a new language). It's a weird time for scala (from the few that I know).


>Does F# offers native builds ? I thought it was CLR only.

i would guess that it will eventually support aot:

https://mattwarren.org/2018/06/07/CoreRT-.NET-Runtime-for-AO...


You can build arch-specific, single file binaries, but I believe the bulk of the executable is a zip file with the .net core runtime and all of your platform agnostic assemblies, so it's not exactly native like you're thinking of


> What other languages offer a similar profile? D? Swift? Kotlin (via LLVM)?

Nim? :)


d and ocaml are both nice. i like ocaml's syntax, but if you don't there is always reasonml, an alternate syntax that is a bit more c-like.


OCaml. Sometimes I feel like the last 20 years of language development have mostly been spent on catching up to OCaml.


Anybody toyed with crystal onto rpi or even microcontrollers ?


Not a lot of options if you don't want curly braces.


Clojure, Haskell, Nim, Python, and I think you could even write JavaScript without using curly braces.


Other than Haskell and Nim, the rest are hardly compiled to machine code.


Well C can be used without those:

   #define BEGIN {


Haha.

To me BASIC syntax always looks like a clunky version of C syntax and the pre-processor code you wrote is just what I have in mind when seeing this.

It always feels like someone wanted to do ML syntax, but didn't go all the way with it.


There are a few Schemes that can compile to C or machine code.


OCaml, maybe?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: