Hacker News new | past | comments | ask | show | jobs | submit login

There are a couple of points where Crystal really feels cleaner and somehow more expressive than Ruby.

The authors of the language avoided aliases (no more size vs. length or inject vs. reduce discussions) and generally there's only one way to do things (Strings are always wrapped in double quotes).

Crystal has abstract classes/modules/methods, generics and method overloading, three powerful techniques which are missing in Ruby entirely and which can be very helpful in some cases.

You can mark global methods as private and you can also mark classes as private. The latter can prevent users of your "shard" (gem) from accessing such classes, pretty much like how Rust modules can be marked for external use or not.

Constructor arguments can be turned into instance variables automatically, if you add `@` to the argument names.

Marking a construct as private happens inline with the definition, unlike in Ruby where it functions as a divider. This makes your code a bit easier to read and you can group methods in any way you like.

I find the built-in JSON, YAML and XML parsers to be very elegant. For the common use cases, you just have to define normal classes with attributes and include the JSON::Serializable module - this will also traverse attributes in search of serializable types. You can also do more complex transformations with annotations - have a look at https://crystal-lang.org/api/0.35.1/JSON/Serializable.html - but writing an HTTP client for some random API in Crystal feels very natural. On top of that, the built-in HTTP client is more than decent (which I can't say about Net:HTTP).

Generally the standard library is packed with goodies and, though the ecosystem is scarce in some areas, it's usually easy to replace and you can get away with less dependencies.

The inferred static typing which allows for union types is a neat choice - it doesn't force you to write types (most of the times) but it does give you some guarantees. I personally prefer to explicitly name my types, especially in public method definitions, because it helps document the code without having to write anything on top, but it's up to you.

To be honest I'm not really missing the metaprogramming aspect. In large Ruby projects this can easily turn into a mess and it makes searching through your codebase a horrid experience. Crystal does have macros but they have some limitations (they operate at compile-time).

Performance is just amazing and you can also build static binaries.

If you like Ruby, I'd really encourage you to give it a try, at least as an experiment to an "alternative Ruby".

To conclude, here are some code samples (shameless plug, but you can also browse https://crystalshards.xyz/ for other projects):

* https://github.com/defense-cr/defense/blob/master/src/defens...

* https://github.com/defense-cr/defense/blob/master/src/defens...

* https://github.com/lipanski/kilometric/blob/master/src/kilom...




I have written almost the identical Scheme interpreters in Ruby and Crystal: [1] and [2]. The biggest difference I have felt between them is the absence of good old Object, which can represent everything at runtime, from Crystal. I had to declare Obj and Val:

  class Obj
  end

  # Value operated by Scheme
  alias Val = Nil | Obj | Bool | String | Int32 | Float64 | BigInt
to define Cons Cell of Scheme:

  # Cons cell
  class Cell < Obj
    include Enumerable(Val)

    getter car : Val            # Head part of the cell
    property cdr : Val          # Tail part of the cell

    def initialize(@car : Val, @cdr : Val)
    end

    ...
  end # Cell
Note that you see generics, Enumerable(Val), and constructor arguments with '@' in the excerpt above.

As for performance, Crystal is faster than Ruby 8.6 times as interpreter and 39.4 times as compiler [3]. You can use Crystal as a superfast (and typed) Ruby interpreter, in a sense.

[1] https://github.com/nukata/little-scheme-in-ruby [2] https://github.com/nukata/little-scheme-in-crystal [3] https://github.com/nukata/little-scheme#performance




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

Search: