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
1
, nil
, true
and false
are objects.- 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"
if object.nil?
do_something
else
do_something_else
end
do_something if this?
do_something unless that?
return if variable = object.method
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
char_count = foo_bar
needed_chars = char_count * 2
spare = 1
a = Array.new(neeeded_chars + spare) # note the spelling error
# 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