From: Eleanor McHugh Date: 2008-05-28T21:48:20+09:00 Subject: Re: The duck's backside On 28 May 2008, at 11:01, Tobias Weber wrote: > def doit(a, b, c = nil) > begin > if c.nil? and b > 0 > c = "ignore" > elsif b.nil? and c > 0 > uaid = "ignore" > else > raise > end > rescue RuntimeError, NoMethodError > raise ArgumentError, "need exactly one number" > end > @http.post("first=#{a}&second=#{b}&third=#{c}") > end This is off the top of my head so the usual caveats apply: def doit a, b, c = nil begin case when b && c raise when b && b.respond_to?(:to_int) uaid = "ignore" if b.to_int > 0 when c && c.respond_to?(:to_int) c = "ignore" if c.to_int > 0 else raise end rescue raise ArgumentError, "need exactly one number" end @post("first=#{a}&second=#{b.to_int}&third=#{c.to_int}") end This makes the exclusion of b and c more explicit, which will make it much easier for a maintainer to understand what's going on. I've also made integer conversion explicit and focused the filtering logic on making sure it's appropriate as that's what you're really trying to achieve, however this kind of belt-and-braces approach suggests that you're tackling the problem from the wrong angle and should look at the data-flow elsewhere in your code. One possibility would be to rejig the whole thing as follows: def doit a, v, param = :second raise ArgumentError, "needs a numeric value" unless v.respond_to? (:to_int) v = "ignore" if (param == :third) && v > 0 @post("first=#{a}&second=#{v if param == :second}&third=#{v if param == :third}") end and then evolve it from there, although it's also pretty damn ugly. Where this is called you could write something along the lines of: if b && c then raise ArgumentError, "needs exactly one additional argument" else doit a, (b || c), (b.nil? ? :third : :second) end which could be further encapsulated as: doit a, b, c = nil raise ArgumentError, "needs exactly one additional argument" if b && c v = b || c raise ArgumentError, "need a numeric parameter" unless v.respond_to? (:to_int) param = b.nil? ? :third : :second v = "ignore" if (param == :third) && v > 0 @post("first=#{a}&second=#{v if param == :second}&third=#{v if param == :third}") end Ellie Eleanor McHugh Games With Brains http://slides.games-with-brains.net ---- raise ArgumentError unless @reality.responds_to? :reason