I am möbius!


Tags: July 9, 2009 (2 comments)

Below are a variety of random notes scribbled down while learning Ruby. Most of this is done from the point of view of someone coming from a background in Python, which is fairly similar.

  • Everything is done through methods (technically these aren't methods, but rather Smalltalk style messages); there is no direct access to properties from outwith the class (or an instance thereof).
  • The print and puts behave similarly: the only difference is that puts outputs a newline after the expression.
  • All objects are created by calling the new method on a class (with the exception of a few primitive types like String, Integer, Array, Hash, Float which have special syntax).
  • All of those primitive types are just objects, and hence are like everything else mutable.
  • Everything is an expression; there are no statements.
  • Unlike Python, there is nothing at the end of the line of an if or while expression. The only syntax whatsoever is the new line.
  • Blocks, such as if and while, when split over more than one line, are ended by an end expression with the same indentation as the line that started the block (i.e., the line on which if, while, etc. occurred on).
  • Methods return the last expression evaluated (ordered by when evaluation began).
  • Constants (including classes) start with an uppercase (ASCII?) letter, variables with lowercase.
  • Strings are bytes in Ruby < 1.9, and characters in Ruby >= 1.9 (use String#bytes to get byte strings then).
  • Single quoted and double quotes string have different meanings, like PHP and unlike Python. Their behaviour is similar to that of PHP: single quoted strings do not evaluate escapes (with the exception of \' and \\, though the latter is only needed if the \ is followed by ') and cannot contain variables; double quoted strings evaluate escapes (a superset of those allowed in C; see below), interpolated code (within #{} where is an expression), and really whacky %-notation (this seems really fucked up as far as I can see — can anyone explain this to me?).

    Escape SequenceMeaning
    \nLine feed (0x0A)
    \sSpace (0x20)
    \rCarriage return (0x0D)
    \tHorizontal tab (0x09)
    \vVertical tab (0x0B)
    \fForm feed (0x0C)
    \bBackspace (0x08)
    \aBell/alert (0x07)
    \eEscape (0x1B)
    \nnn Byte (Ruby < 1.9) or character (Ruby >= 1.9) with octal value nnn
    \xnn Byte (Ruby < 1.9) or character (Ruby >= 1.9) with hexadecimal value nn
    \unnnn Unicode code point U+nnnn (Ruby 1.9 and later)
    \cx Control-x
    \C-x Control-x
    \M-x Meta-x
    \M-\C-x Meta-control-x
    \x Character x (e.g., \")
  • Strings can be used as arrays of ordinal values (e.g., "a"[0] == 0x61 evaluates to true).
  • The true and false keywords are both all lowercase.
  • a..b represents a range between two Integers a and b.
  • A slice of an Array or String can be got by either foo[1,3] (comma as delimiter between start index and length) or foo[1..3] (a range), for String foo. Note with the former syntax both must be present, and both most be positive (negative indices do not work); with the latter syntax negative indices do work as the end of the range, but are slightly weird. (-1 is the end-of-string, so -2 must be used to not get the final character. This makes foo[x..y] identical to foo[x..(foo.length + y)] when y is negative.)
  • nil is the null keyword.
  • Only false and nil evaluate to false, everything else (including 0) evaluates to true.
  • =~ is a matching operator for Strings to evaluate regular expressions (which are, like in Perl, delimited by /). It evaluates to the first position where a match was found or nil.
  • Hashes are identical to dicts in Python, but use => for assignment instead of :.
  • ARGV (note uppercase) contains command line arguments (as an Array).
  • The methods to_i (to Integer), to_s (to String), to_f (to Float) are used to convert to primitive types.
  • Method names often end in ! if they mutate the variable value (this leads to String having methods like chop! and chop: the former mutates the variable, the latter returns a mutated copy).
  • Parenthesis are optional for method calls, provided their non-occurrence does not make it ambiguous.
  • unless is a negative if expression
  • A case block goes through all when sub-blocks (which have equal indenting to the case block), checking them to see if, when compared with === (which in general is identical to ==), the case matches the when. Execution stops after the first matching when. The === means you can do cool stuff like having a range for a when.
  • Global variables are prefixed with $, instance variables @, and class variables @@.
  • while blocks are like those of any other language, and until blocks are their negated equivalents, like unless are those of if. break does what would be expected, next is equivalent to continue in most languages, and redo restarts the current iteration.
  • for x in y works like in Python.
  • Iterators have an interesting syntax: [1,2,3,4].each {|e| puts e.to_s }.
  • Iterators are defined like generators are in Python, using yield. Execution of them terminates upon reaching return. retry returns to the start of the function block of the iterator.
  • self can be omitted when working within a class/object.
  • < is used for inheritance (e.g., class Foo < Bar).
  • super, when called from a method of a subclass, calls the same method on the superclass (optionally with arguments).
  • public, protected, private can be put on the line before the first method within a class of each type (the keywords apply until end).
  • Namespaces are defined by module Foo … end. A module can be imported into the current scope by include (e.g., Math::PI; include Math; PI).
  • :: is used to access constants in another module.
  • begin … rescue … end is the same as Python's try … except.
  • Classes can be added to just by having another class block with the same name.
  • Accessors for instance variables can easily be added with attr_reader :foo, attr_writer :foo, and attr_accessor :foo, the last of which is equal to specifying both of the former.
  • The initialize method is called on object initialization.
  • Comments until end of line begin with #, longer comments can be added by =begin and =end delimiting them.
  • elsif, not else if, , elif or anything else. Just elsif.

Page:  1