| Crystal has meaningfully different syntax from Ruby in some important places: * Strings cannot be single-quoted in Crystal. Single quotes are used for character literals, like C. * The two languages differ substantially in how keyword arguments are specified. In Crystal, any argument can be specified by name as well as position. * In Crystal a 'rocket-style' dict literal (i.e. `{ "foo" => "bar" }`) is a different type (Hash) from a 'keyword-style' dict literal (`{ foo: "bar" }`, a NamedTuple). * Hashes are typed (inferred at the time of creation). You can't use keys and values of different types than what was in the hash when you created it. You _always_ have to specify a type for empty hashes, which means that any Ruby code that does `x = {}` and then stuffs things into `x` has to be rewritten. * NamedTuples raise an error if you try to read or write a nonexistent key. Hashes raise an error if you try to read a nonexistent key. * Crystal does not have singleton classes (`class << self`). The Module class doesn't exist. You can't execute code in class definitions (like constant initializations). Generally speaking, a lot of the very dynamic Smalltalk-y features Ruby devs take for granted are not present. * `private`/`protected`/`public` are keywords, not methods, and they must be applied to each method individually (`private def...`). There's a lot else. Now, a lot of these changes are good and fix issues that Ruby can't because of the need for backwards compatibility. This isn't a criticism of the language. The fact remains that Crystal's superficial similarity to Ruby hides a lot of substantial differences (a problem Elixir suffered from for a while as well). Translating simple code by hand is not difficult, but rewriting a larger project would be a huge undertaking. |
Depends on what method you use to read it. If you use [], what you describe is true, but if you use the nilable variant, []?, it is not. But yes, having to handle and think of nilability is certainly a big change that will affect a lot of code.