Ruby: pros and consEdit

Things I like about Ruby

  • Total object-oriented; even 1, nil, true and false are objects.
  • Looks very clean because punctuation is minimal
    • Statements don’t need semi-colons to terminate them (but you can put them on if you want)
    • Statements automatically terminated by newlines, unless continuation is obvious:
a_statement; another_statement
puts "this statement spans two lines " +
     "thanks to the plus sign on the line above"
  • Various, natural ways of expressing flow control decisions:
if object.nil?
  do_something
else
  do_something_else
end

do_something if this?

do_something unless that?

return if variable = object.method
  • No need to declare variables before use
  • Built-in RSS support in the standard library
  • Advanced flow control structures

Apart from the basic while loops and case statements, Ruby also provides exception handling (raise and rescue) for unexpected or error conditions, throw/catch as an alternative means of jumping out to a wider scope (generally not used for error conditions), and finally, continuations which can be used (or abused) to do pretty much anything you want.

Continuations are a special favorite of mine as they allow you to jump back to a previously signalled place in the call stack with virtually no limitations (hence my statement about "use or abuse").

Things I don’t like about Ruby

  • No need to declare variables before use (can lead to hard to spot run-time errors):
char_count = foo_bar
needed_chars = char_count * 2
spare = 1
a = Array.new(neeeded_chars + spare) # note the spelling error
  • Autogenerated accessors are great if and only if you want objects passed in by reference; if you want to copy the values then things are a royal pain.
# this will set up autogenerated accessors (by reference)
attr_accessor :ivar1

# this is will break if you pass nil
# the problem is that nil raises an exception if you send it a dup message
# (nil is actually a singleton object)
def ivar2=(newvalue)
  @ivar2 = newvalue.dup
end

# this obvious workaround fails
# nil devilishly responds "true" here, then raises
def ivar3=(newvalue)
  if newvalue.respond_to?("dup")
    @ivar3 = newvalue.dup
  else
    @ivar3 = newvalue
  end
end

# this workaround fails too
# it fixes the problem with nil, but breaks if you pass a Fixnum
def ivar4=(newvalue)
  if newvalue and newvalue.respond_to?("dup")
    @ivar4 = newvalue.dup
  else
    @ivar4 = newvalue
  end
end

# it seems that the only work around is to catch exceptions in the accessor (yuck!)
# as an Objective-C/Cocoa programmer, this really looks hideous
def ivar5=(newvalue)
  begin
    @ivar5 = newvalue.dup
  rescue TypeError
    @ivar = newvalue
  end
end

# slightly better
def ivar6=(newvalue)
  @ivar6 = newvalue.dup
rescue TypeError
  @ivar = newvalue
end

# shortest form I've found so far
def ivar7=(newvalue)
  @ivar7 = (newvalue.dup rescue newvalue)
end