Found another ruby gotcha when calling methods declared with default argument values:
irb(main):004:0> def a( b=1,c=2,d=3) irb(main):005:1> print "#{b} #{c} #{d}\n" irb(main):006:1> end => nil irb(main):007:0> a(c=23) 23 2 3 => nil
A python programmer would have expected this to print
2 23 3
as when calling the function we are saying we want c to be 23 and the other arguments to be left at their default values. Ruby appears to be ignoring the 'c=' bit when the function is being called so the first argument 'b' gets the value 23.
Pity, this python trick simplifies calling functions with lots of default parameters: you don't have to get the order of the parameters right or specify the correct default values of arguments before the one you are having to specify a value for. I should be calling this with:
irb(main):007:0> a(b=1, c=23)
i.e passing 'b=1' even though the declaration should tell ruby what the default for that should be. The 'b=' and 'c=' are only serving to help me selfdocument my code.
Ruby's behaviour is C/C++ish i.e. primitive.
UPDATE:
1 def fun_with_text(text, args={}) 2 text = text.upcase if args[:upcase] 3 text = text.downcase if args[:downcase] 4 if args[:find] and args[:replace] 5 text = text.gsub(args[:find], args[:replace]) 6 end 7 text = text.slice(0, args[:truncate_at]) if args[:truncate_at] 8 return text 9 end 10 11 fun_with_text("Foobar", {:upcase => true, :truncate_at => 5}) 12 # => "FOOBA" 13 fun_with_text("Foobar", :upcase => true, :truncate_at => 5) 14 # => "FOOBA" 15 fun_with_text("Foobar", :find => /(o+)/, :replace => '\1d', :downcase => true) 16 # => "foodbar"


Interesting. So, Ruby doesn't really have keyword arguments, only positional arguments? Unless you use some kind of varargs/dictionary, I guess (from the cookbook example).
BTW, I think you meant to say that a Python programmer would expect "1 23 3" as output rather than "2 23 3".