From: Piergiuliano Bossi Date: 2004-03-05T01:49:50+09:00 Subject: Re: Ruby won, of course 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. :-) Ciao, Giuliano -- If you want to send me an email in the address you have to write 'p', then a dot, followed by 'bossi' at 'quinary', another dot and 'com' at last