From: Robert Klemme Date: 2004-03-05T02:14:51+09:00 Subject: Re: Ruby won, of course "Piergiuliano Bossi" schrieb im Newsbeitrag news:c27mo1$7nr$1@lacerta.tiscalinet.it... > Robert Klemme wrote: > >>You are right, my fault. Fact is that having eliminated combine_results > >>method I now combine values using '&&' (or 'and'), which in turn > >>performs a short-circuit evaluation ==> if the failing test is in the > >>first group combined through '&&' the second group will never be > > > > evaluated. > > > >>I start thinking that combine_results cannot be avoided... > > > > > > I'm afraid you're a bit confused now. :-) What do you want > > combine_results for? It does not make a difference, because you eval'ed t > > before. And even if you didn't, switching order is sufficient. You did > > (with the slight modification of pulling v=eval(t) out of the string): > > > > def check(*tests) > > stack = caller.map {|m| m[/\w*(?=')/]}.compact.reverse.join " " > > tests.inject(true) {|ret, t| v=eval(t); puts "#{v ? 'pass' : 'FAIL'} > > .... (#{stack}) #{t.strip}"; ret && v} > > end > > > > It doesn't matter whether "ret && v" short circuits or not, because you > > did eval it already. And even if you didn't you could do "eval(t) && ret" > > which would always eval. > > Ok, I have to repost the code, otherwise we don't understand each other. > > ****************CUT HERE**************** > def check(*tests) > stack = caller.map {|m| m[/\w*(?=')/]}.reverse.join(" ").strip > tests.inject(true) {|ret, t| puts "#{(v=eval(t))?'pass':'FAIL'} ... > (#{stack}) #{t}"; ret && v} > end > > def test_plus > check( > "1 + 2 == 3", > "1 + 2 + 3 == 6", > "-1 + -3 == -4") > end > def test_multiply > check( > "2 * 2 == 4", > "3 * 5 == 15") > end > > def test_aritmetic > test_plus && > test_multiply > end > > def test_math > test_aritmetic > end > > result = test_math > puts "result=#{result}" > ****************CUT HERE**************** > > I'm talking of the '&&' inside test_aritmetic: using inject directly > instead of combine_results makes executing the first group of test only. > > Try to change first test from "1 + 2 == 3" to "1 + 1 == 3" ==> you will get: > ****************CUT HERE**************** > FAIL ... (test_math test_aritmetic test_plus) 1 + 1 == 3 > pass ... (test_math test_aritmetic test_plus) 1 + 2 + 3 == 6 > pass ... (test_math test_aritmetic test_plus) -1 + -3 == -4 > result=false > ****************CUT HERE**************** > > instead of > > ****************CUT HERE**************** > FAIL ... (test_math test_aritmetic test_plus) 1 + 1 == 3 > pass ... (test_math test_aritmetic test_plus) 1 + 2 + 3 == 6 > pass ... (test_math test_aritmetic test_plus) -1 + -3 == -4 > pass ... (test_math test_aritmetic test_multiply) 2 * 2 == 4 > pass ... (test_math test_aritmetic test_multiply) 3 * 5 == 15 > result=false > ****************CUT HERE**************** > > The former is wrong. > > In order to fix this I should use some form of inject in test_aritmetic > too, creating a duplication that can be removed reintroducing > combine_results only. That method was defined as: > > ****************CUT HERE**************** > def combine_results(*tests) > tests.inject {|t1, t2| t1 && t2} > end > ****************CUT HERE**************** > > I hope that now it is clear. :-) Yes, it is. But: def combine_results(*tests) tests.all? end And: you still don't need combine_results(): def test_aritmetic [ test_plus, test_multiply ].all? end :-)) Regards robert