From: ptkwt@...1.aracnet.com (Phil Tomson) Date: 2001-11-03T16:29:10+09:00 Subject: [ruby-talk:24251] Re: Too much eval evil? (tell me why I shouldn't do this) In article <2334FC218D0FD6499D8B685EB518AED81FDD59@us-exchange.mosaicsoftware.net>, Ryan Leavengood wrote: >> Let's say I've got a string which has some ruby variables in it and I >> want each of those variables to take on a range of values and then I >> want to evaluate that string given every combination of those values >> (a cartesian product). And of course I want to be able to use this >> with a variable number of varying variables, so my cartesian product >> function has to work given any number of variables. > >This was just too interesting of a challenge for me to pass up. Here is >my version (with no evaling): > ># I chose the name "cascade" since we are cascading down through the >array >def cascade(a, list = [], &block) > return list if list.size == a.size > a[list.size].each do |item| > list << item > cascade(a, list, &block) > if list.size == a.size > block.call(list) > end > list.slice!(-1) > end > list >end > >a = [(0..20), (43..150), ['z','yz','xyz','xz','zz']] >cascade(a) do |list| > puts "width is: #{list[0]}, length is: #{list[1]}, hight is: >#{list[2]}" >end > >This runs about twice as fast as the one Thomas originally wrote. It >could be probably be cleaned up, but it seems to work pretty well. >Using an array instead of a hash guarantees the order in which the >variables will be evaluated. Being able to call a block gives you more >flexibility than just evaling a string. Also, when dealing with ranges >you don't really need to turn them into arrays...they respond to "each" >correctly. I like Ryan's solution better than the one proposed by Thomas (it seems a lot cleaner), but I can see that Thomas' solution has an advantage: What if one were using some kind of templating system where you have a file which contains embedded Ruby code (like the one I proposed a few days back), then you actually need to have the names of the variables produced in the cartesian product code match the names of the variables in the template file - it looks like the original solution (with a few modifications) could do that... I think I'll try it. This thread turned out to be surprisingly timely, I was just thinking of some way of doing something similar to this in conjunction with my Template system for generating test code. Phil