From: Reimer Behrends Date: 2002-09-02T09:39:20+09:00 Subject: Re: Ruby aesthetics Gavin Sinclair (gsinclair@soyabean.com.au) wrote: > From: "Reimer Behrends" [...] > > To be used as follows: > > > > squares_less_than_10 = numbers.condmap{|x| x**2 if x < 10 } > > That's very nice indeed. Would there be any support for adding this, or > something like it, to the language standard? Maybe not, since there's a > redundancy (collect{...}.compact). But I'd like to see it for sure. The question is whether it's essential enough for many people to have it. I see it more as a convenience feature; it does not add much in terms of essential functionality, as you say. > > In general, you do not want to expand the language when existing > > abstraction mechanisms can already capture the same thing adequately and > > with more room for customization. > > True, but what about getting all pairs of number less than 10 whose > combination mulitplies to greater than 25? > > result = [[a,b] for a in (1...10) for b in (1...10) if a * b > 25] What you seem to be getting out of the list comprehension facility mostly is the generation of pairs. A functionality that could arguably be separate from a list comprehension facility. (Also, if the above is to be legal Python code, it would be range(1, 10) instead of 1...10). We can try the following to enumerate pairs: module Enumerable def pair_with(other) result = [] each do | item | other.each do | item2 | result << [item, item2] end end result end end p((1...10).pair_with(1...10).select{|x, y| x * y > 25}) > This construct hasn't had much popularity in this thread, but I think > it would be a worthwhile addition to the language. It's simply a > beautiful abstraction. (I know a little about functional programming, > but cannot be said to have a background in it: my appreciation for > list comprehensions is more mathematical.) It can be written in Ruby (or as a C extension), if you are so inclined. Enum.all(1...10, 1...10) {|x,y| [x,y] if x * y > 25} Enum.all(numbers) {|x| x ** 2 if x < 10 } Enum.all(1..3, 1..4) Below is a quick & dirty implementation in Ruby (the module name "Enum" and the method name "all" probably aren't good choices either, but this is just proof of concept). Reimer Behrends module Enum def self.all_recurse(result, prefix, ranges, &block) if ranges.size == 1 then prefix.push nil ranges[0].each do | prefix[-1] | if block_given? then item = yield *prefix result << item unless item.nil? else result << prefix.clone end end prefix.pop else prefix.push nil ranges[0].each do | prefix[-1] | all_recurse(result, prefix, ranges[1..-1], &block) end prefix.pop end end private_class_method :all_recurse def self.all(*args, &block) result = [] all_recurse(result, [], args, &block) if args.size > 0 result end end