Skip to content

Instantly share code, notes, and snippets.

@paddor
Last active August 18, 2016 16:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paddor/cb5325517ff2e605828841f8a4b47f7c to your computer and use it in GitHub Desktop.
Save paddor/cb5325517ff2e605828841f8a4b47f7c to your computer and use it in GitHub Desktop.
from Ruby to Crystal
from Ruby to Crystal:
* compiled to one binary
* (optional) type restrictions
* there's a class Bool (values are true and false)
* Nil is the type of nil (not NilClass)
* very DRY: def initialize(@name)
* nice way to avoid alias_method_chain: previous_def
* @@var is valid only in that class and its instances, not subclasses
* file-global functions can be called from within a method (foo() or explicitly ::foo())
* Strings are immutable and always UTF-8
* "..." are string literals, but not '...' ('a' is a Char as in C/C++)
* multi-line, indented String-literal with escaped newlines automatically undents (all leading whitespaces are removed)
* fancy strings only with %(...), %[...], %{...}, and %<...>
* there is Tuple and NamedTuple which are fixed-size, immutable, and stack-allocated
* only one Hash syntax: { :bla => "bli", "foo" => "bar" } ({ bla: "bli"} is a NamedTuple)
* regular parameters can be given as named parameters in any order (def foo(a,b) ... end; foo a: 5, b: "baz") <3
* internal/external argument names: def increment(value, by amount) value + amount end; increment(5, by: 3)
* method overloading, depending on number of positional parameters, their types, block given or not, and even named parameters <3
* there is #finalize <3
* Go-like channel (Channel) for communication between green threads (#spawn) <3
* "with obj yield", e.g. "with self yield" will set a special object as default receiver for methods inside the block
* there's struct (a inherits from Struct < Value < Object, whose instances are stack-allocated and are passed by value)
* otherwise a class inherits from Reference < Object, whose instances are passed by reference)
* private/protected are prepended to def: private def foo(bar : Bar)
* there's no "public" keyword, since it's the default
* protected means: caller is either of same type or in same namespace
* private top-level methods are only visible in the current file
* Object is the hierarchy root
* explicit return type of method, if needed, at the end of the signature (not like in C/C++/Java)
* there's no String#to_sym, as all Symbol's of the program are known at compile-time, and each one will be a Int32
* there is enum (abstract struct Enum)
* there is Pointer and Slice
* there are abstract classes and abstract methods
* lib, alias, ifdef, fun, ...: syntax for writing C bindings built-in
* no uppercase methods (??) => Channel(String) is generics syntax (a Channel for String objects)
* green-threads (Fiber's) only, so far
* #map &.name.upcase (more flexible than &:name in Ruby, it's chainable)
* $var are file-global (??)
* $var, @var, @@var have to be typed (or initial type-deducable value given)
* []/{} has to be typed (compiler can't infer type of nothing)
* there are marcros, and ifdef
* method API doc is copied from above if it's "ditto"
* record Entry???
* LibC
* there are macros, and they're very powerful
* getter/setter/property (macros) instead of attr_reader, attr_writer, attr_accessor
* there are macro defs, which are methods defined in a superclass with something in their body be replaced by the actual subclass
* String#camelcase
* no "and" or "or", only && and ||
* heredocs are always of form "<<-EOF", so closing delimiter can always be indented; automatically undents content as much as the closing delimiter is indented
* break (and return?) inside a block return from the method that yielded
* next inside a block just returns from the block
* break and return can't be used inside a captured block (Proc object)
* procs from method: instead of ->{ meth }, just ->meth, even on explicit receivers (if method takes args, types must be specified): p = ->str.count(Char); p.call('c')
* no while/until statement modifier
* no "do ... end while <condition>" (just do "loop do ...; break unless <condition>")
* mandatory parenthesis around arguments when defining a method to avoid ambiguity (e.g.: def foo(bar) : Bool)
* no aliases: no Enumerable#inject (only #reduce), no Enumerable#collect (only #map), not sure about #find/#detect and #select/#find_all
* no String#length, only #size, same for Array
* not only #[], but also #[]? which could return nil if index inexistent (#[] would raise)
* raise "msg" raises Exception
* syntax "raise Klass, msg" doesn't exist. it's just "raise Klass.new(msg)"
* there's no $! in the rescue block, just catch it like this: "rescue e : Exception"
* PCRE is used instead of Oniguruma
* fancy regex syntax: %r(...) or %r{...} or %r[...] or %r<...>
* there are 'inherited', 'included', 'extended', and 'method_missing' hooks (as macros)
* forward_missing_to macro
* there's only require, but it's intelligent: "foo" requires "foo" or "foo/foo.cr" from require path, "./foo" is like require_relative, and "foo/*" and "foo/**" work as expected
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment