From: Daniel Schierbeck Date: 2005-10-29T00:42:11+09:00 Subject: Re: Cleaner syntax for .map (is there already a way, or ruby2 idea?) David A. Black wrote: > Hi -- > > On Fri, 28 Oct 2005, Daniel Schierbeck wrote: > >> David A. Black wrote: >> >>> Hi -- >>> >>> On Fri, 28 Oct 2005, Daniel Schierbeck wrote: >>> >>>> Daniel Schierbeck wrote: >>>> >>>>> David A. Black wrote: >>>>> >>>>>> I know that people.every could return >>>>>> some kind of generator or enumerator, which could then be fed >>>>>> "email_addr" symbolically... >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> module Enumerable >>>>> def every >>>>> enum, obj = self, Object.new >>>>> obj.define_method :method_missing do |name, *args| >>>>> enum.map { |element| element.send(name, *args) } >>> >>> >>> >>> If you must do this, you'd probably want each rather than map there. >> >> >> Nope. I wan't it to return an array of the values returned. > > > Oh right, never mind. > >> ["john", "sylvia", "sarah"].every.upcase -> ["JOHN", "SYLVIA", "SARAH"] >> >> That's of course not a very good example. This would probably be better: >> >> addresses = contacts.every.email_addr >> >> As opposed to >> >> addresses = contacts.collect { |contact| contact.email_addr } > > > I strongly prefer the latter. You've gone out of your way to make it > long and wordy :-) > > addresses = contacts.map {|c| c.email_addr } > That's of course a matter of taste, but I don't like single-letter variables. Abbreviations of long words can do, but the variable name should reflect the object it is referencing. Furthermore, I often use `collect' instead of `map' simply because that's what I'm doing: collecting email-addresses from a list of contacts. >> But I agree that the dot syntax is bad, I was just proving that it >> could easily be done. This would be better: >> >> addresses = contacts.every(:email_addr) > > > There was an RCR once for enum.map(:method) {|x| ... } but it was > rejected. > I don't see why a method such as `map' should work that way - it isn't implied by the method name. >> And maybe even have a `with_every' method: >> >> contacts.with_every(:email_addr) do |email_addr| >> puts " - " + email_addr >> end > > > "with_every" feels like the wrong word, though. It suggests that > they're all being used at the same time. Maybe: > > contacts.each_send(:email_addr) > > or something. > > Maybe. `with_each' would also do. But still I think it is inconsistent to have `each' yield each object in a collection and `each_send` yield the result of calling a method on those objects. I'd rather we have `every' handle the latter. # calls `method' on each object in `collection' # and returns the return values of those calls # in an array collection.every :method # calls `method' on each object in `collection' # and yields the return values collection.with_every :method do |result|; end They could of course both be contained in a single method, which both returned an array and yielded the return values. I'm not suggesting that we put this in the Ruby Core, but I think it's a great library method. Cheers, Daniel