From: Robert Klemme Date: 2004-10-20T22:14:30+09:00 Subject: Re: Too many default argument values! "Matt Maycock" schrieb im Newsbeitrag news:e86cebfb04102005431b958b4f@mail.gmail.com... > Putting everything in a default hash is sort of a bad idea. > > ------------------------- code ------------------------- > [ummaycoc@localhost ummaycoc]$ ruby -e ' > DEFAULT_ARGS = {:foo => :meow, :santa => :love}.freeze > puts("-" * 50) > p DEFAULT_ARGS > def test(arg1, opt_args=DEFAULT_ARGS) > puts "Test: #{opt_args.inspect}" > end > > puts > test(:hey) > puts > test(:two, :foo => 1, :ruby => :language)' > -------------------------------------------------- > {:santa=>:love, :foo=>:meow} > > Test: {:santa=>:love, :foo=>:meow} > > Test: {:ruby=>:language, :foo=>1} > ------------------------- end code ------------------------- > > Actually using it, you lose the fact that santa maps to love (thus > everything in the `optional' hash is `mandatory') > > a much better idea would be: > > DEFAULT_HASH = { ... } > def myFunc(arg1, ..., argN, optHash={}) > DEFAULT_HASH.keys.each {|k| > optHash[k] = DEFAULT_HASH[k] unless optHash.include?(k) > } > .... > end > > > This gives you what you actually want. I hope. True. I forgot that. Alternatives: DEFAULT_HASH = { ... }.freeze def myFunc(a, b, args={}) @a = a @b = b @foo = args[:foo] || DEFAULT_HASH[:foo] .... end or DEFAULT_HASH = { ... }.freeze def rect(a, b, args = DEFAULT_HASH) tmp = DEFAULT_HASH.dup.update( args ) ... @a = a @b = b @foo = tmp[:foo] ... end Kind regards robert > > > On Wed, 20 Oct 2004 18:24:24 +0900, Robert Klemme wrote: > > > > "Tim Hunter" schrieb im Newsbeitrag > > news:j%gdd.27795$zA3.4433422@twister.southeast.rr.com... > > > Looking for coding style advice... > > > > > > I'm trying to write a method that describes a rectangle. A rectangle is > > > defined by the x,y coordinates of its upper-left corner and its width > > and > > > height. These values are required. Optionally, the rectangle can have > > > "styles," like the fill color and the stroke color. Also optionally, the > > > rectangle can have rounded corners, if you specify how much rounding you > > > want in the x and y directions. (The default is square corners.) > > > > > > The method I started with is: > > > > > > def rect(x, y, width, height, rx=0, ry=0, styles=nil) > > > # blah, blah, blah > > > end > > > > > > Where the styles argument (if present) is a Hash formed by the usual > > > trailing key=>value pairs. All very standard Ruby. > > > > > > I was thinking that you'd create a square-corner rectangle like this: > > > > > > canvas.rect(10, 10, 20, 30, :fill=>'black', :stroke='red') > > > > > > But of course that doesn't work, because the styles hash > > > "{:fill=>'black', :stroke=>'red'}" gets assigned to rx, not to styles. > > > > > > Of course, within rect I could test the class of rx and/or ry and if > > it's a > > > Hash, assign it to styles, but that seems kludgy and insufficiently > > > Rubyish. I could divide rect into two methods, rect and rounded_rect, > > but > > > that means that the user has to remember an extra method name. I could > > make > > > rx and ry required arguments. Blech. > > > > > > Thoughts? > > > > Put all (optional) args into the hash and use a default hash > > > > def rect(x, y, width, height, args={:rx=>0, :ry=>0}) > > # blah, blah, blah > > p x > > p y > > p width > > p height > > p args > > end > > > > Alternative with slightly better performance: > > > > DEFAULT_RECT_ARGS = { > > :rx => 0, > > :ry => 0, > > }.freeze > > > > def rect(x, y, width, height, args=DEFAULT_RECT_ARGS) > > .... > > > > >> rect(10, 10, 20, 30, :fill=>'black', :stroke=>'red') > > 10 > > 10 > > 20 > > 30 > > {:stroke=>"red", :fill=>"black"} > > > > or even > > > > def rect(args=DEFAULT_RECT_ARGS) > > .... > > > > Kind regards > > > > robert > > > > > > > -- > There's no word in the English language for what you do to a dead > thing to make it stop chasing you. > >