Thursday, December 30, 2010

Ruby: Inconsistencies

This is a growing list:
  • String#concat
    • Should be String#concat!
    • I guess it's meant to resemble #insert, #delete, #fill, #replace, #clear, etc., but I wish those had "!" too, like #compact!, #reject!, #slice!, etc. There should be 2 versions of all these, but because there is no "!", the non-mutating versions can never be.
  • Hash#update is a synonym for Hash#merge!
    • I have to remember which one has the "!"
    • Hash#invert does *not* mutate. How do I remember all this?
    • Even worse, Set#merge (no "!") mutates, unlike Hash#merge.
  • Set#add? and Set#delete?
    • These mutate.
  • s.chomp!.upcase
    • Can fail, since String#chomp! can return nil
  • Array#fetch(i) (and Hash#fetch(k)) can raise IndexError
    • Should be Array#fetch!(i)
    • Block and multi-arg version could drop the "!"
  • String#each does not exist in Ruby1.9, while #each_char does not exist in 1.8
    • We cannot write forward-compatible code!
    • Soln: s.split("")
  • '0x10'.hex and '0x10'.oct are same, but
    • '010'.hex and '010'.oct are different
  • Given: a = [1,2,3]
    • a[2] == 3
    • a[3] == nil
    • a[4] == nil
    • a[2,1] == [3] (and a[2,2] == [3] as well)
    • but a[3,1] == []
    • while a[4,1] == nil
  • For Arrays
    • a[x,y] = [nil] substitutes the slice
    • a[x,y] = z     substitutes [z], but ...
    • a[x,y] = nil   deletes the slice! (fixed in 1.9)
  • inspect/to_s
    • There used to be a clear distinction, like Python's __repr__/__str__, but 1.9 often (though not in all cases) erases that useful distinction.
  • Array   Float   Integer   String 
    • Those are Kernel functions, not constants.
  • ...
Also see Ruby Best Practices, a great book.

No comments:

Post a Comment