[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

[Facets] Array#send_to_each

Daniel Schierbeck

4/18/2006 2:58:00 PM

Browsing through the list of method, I couldn't find a method that did
what I wanted it to, although Enumerable#every is close.

class Array
def send_to_each(symbol, *args)
collect{|obj| obj.send(symbol, *args)}
end
end

arr = ["cat", "dog", "monkey"]
arr.send_to_each(:upcase) #=> ["CAT", "DOG", "MONKEY"]
arr #=> ["cat", "dog", "monkey"]
arr.send_to_each(:upcase!) #=> ["CAT", "DOG", "MONKEY"]
arr #=> ["CAT", "DOG", "MONKEY"]

I'm only putting it in Array, and not Enumerable, because I'm not sure
it will be of use to hashes etc.

Take it or leave it :P


Cheers,
Daniel
7 Answers

Vincent Foley

4/18/2006 4:54:00 PM

0

That's nice, although I think using collect isn't that big of a deal.
You should check out the manual [1] for F-Script, especially chapter
16. It's about operators for aggregates. You can think of F-Script as
a mix of Smalltalk and Cocoa with APL thrown in for cool array
operations.

Maybe we could define an operator in Ruby to do that...

module Enumerable
def %(symbol, *args)
map { |e| e.send(symbol, *args) }
end
end

%w(hello world foo bar baz) % :upcase

[1] http://www.fscript.org/download/do...

Robert Klemme

4/18/2006 5:11:00 PM

0

Vincent Foley wrote:
> That's nice, although I think using collect isn't that big of a deal.

We could add arguments to map / collect. Behavior would then change
like this: if there is no block and at least one arg is present the new
behavior is chose, if there is a block and no args the old behavior is
chosen else error. This would not break any old code.

> You should check out the manual [1] for F-Script, especially chapter
> 16. It's about operators for aggregates. You can think of F-Script as
> a mix of Smalltalk and Cocoa with APL thrown in for cool array
> operations.
>
> Maybe we could define an operator in Ruby to do that...
>
> module Enumerable
> def %(symbol, *args)
> map { |e| e.send(symbol, *args) }
> end
> end
>
> %w(hello world foo bar baz) % :upcase

This does not work - the syntax with arguments is illegal:

>> Object.new % 1,3
SyntaxError: compile error
(irb):2: syntax error
Object.new % 1,3
^
from (irb):2
from :0

Kind regards

robert

Ross Bamford

4/18/2006 5:42:00 PM

0

On Tue, 18 Apr 2006 15:58:11 +0100, Daniel Schierbeck
<daniel.schierbeck@gmail.com> wrote:

> Browsing through the list of method, I couldn't find a method that did
> what I wanted it to, although Enumerable#every is close.
>
> class Array
> def send_to_each(symbol, *args)
> collect{|obj| obj.send(symbol, *args)}
> end
> end
>
> arr = ["cat", "dog", "monkey"]
> arr.send_to_each(:upcase) #=> ["CAT", "DOG", "MONKEY"]
> arr #=> ["cat", "dog", "monkey"]
> arr.send_to_each(:upcase!) #=> ["CAT", "DOG", "MONKEY"]
> arr #=> ["CAT", "DOG", "MONKEY"]
>

Not to detract from this (which is IMHO a good addition), but one of my
favourite facets is Symbol#to_proc:

require 'facet/symbol/to_proc'
arr = ["cat", "dog", "monkey"]

arr.collect(&:upcase)
# => ["CAT", "DOG", "MONKEY"]

arr.collect(&:reverse)
# => ["tac", "god", "yeknom"]


--
Ross Bamford - rosco@roscopeco.remove.co.uk

Daniel Schierbeck

4/18/2006 5:50:00 PM

0

Vincent Foley wrote:
> module Enumerable
> def %(symbol, *args)
> map { |e| e.send(symbol, *args) }
> end
> end
>
> %w(hello world foo bar baz) % :upcase

There are two problems with your code; the first thing is that normal
operators (`+', `-', `*', etc.) don't allow multiple arguments. The
second is that your method would only work on Enumerable objects whose
#each method yielded a single object to the block.

{"foo" => "bar", "baz" => "bur"}.send_to_each(:upcase)
#=> NoMethodError: undefined method `upcase' for ["baz", "bur"]:Array

I think it's a bad idea to add methods that place further restrictions
on the depending methods, here #each. If #each has been implemented
following to the requirements of Enumerable, every method of it (that
only uses #each) should work.


Cheers,
Daniel



Daniel Schierbeck

4/18/2006 6:02:00 PM

0

Ross Bamford wrote:
> ... one of my favourite facets is Symbol#to_proc:
> require 'facet/symbol/to_proc'
> arr = ["cat", "dog", "monkey"]
>
> arr.collect(&:upcase)
> # => ["CAT", "DOG", "MONKEY"]
>
> arr.collect(&:reverse)
> # => ["tac", "god", "yeknom"]

Mine, too. Its function is just not as clear as the more descriptive
#send_to_each, although I'd happily use both.

Daniel

Gavin Sinclair

4/19/2006 6:26:00 AM

0


Daniel Schierbeck wrote:
> Browsing through the list of method, I couldn't find a method that did
> what I wanted it to, although Enumerable#every is close.
>
> class Array
> def send_to_each(symbol, *args)
> collect{|obj| obj.send(symbol, *args)}
> end
> end
>
> arr = ["cat", "dog", "monkey"]
> arr.send_to_each(:upcase) #=> ["CAT", "DOG", "MONKEY"]
> arr #=> ["cat", "dog", "monkey"]
> arr.send_to_each(:upcase!) #=> ["CAT", "DOG", "MONKEY"]
> arr #=> ["CAT", "DOG", "MONKEY"]

I think the following are better style:

arr = ["cat", "dog", "monkey"]
arr.map { |e| e.upcase }
# -> ["CAT", "DOG", "MONKEY"]
arr
# -> ["cat", "dog", "monkey"]
arr.each { |e| e.upcase! }
# -> ["CAT", "DOG", "MONKEY"]
arr
# -> ["CAT", "DOG", "MONKEY"]

Cheers,
Gavin

Daniel Schierbeck

4/19/2006 7:11:00 AM

0

Gavin Sinclair wrote:
> Daniel Schierbeck wrote:
>> Browsing through the list of method, I couldn't find a method that did
>> what I wanted it to, although Enumerable#every is close.
>>
>> class Array
>> def send_to_each(symbol, *args)
>> collect{|obj| obj.send(symbol, *args)}
>> end
>> end
>>
>> arr = ["cat", "dog", "monkey"]
>> arr.send_to_each(:upcase) #=> ["CAT", "DOG", "MONKEY"]
>> arr #=> ["cat", "dog", "monkey"]
>> arr.send_to_each(:upcase!) #=> ["CAT", "DOG", "MONKEY"]
>> arr #=> ["CAT", "DOG", "MONKEY"]
>
> I think the following are better style:
>
> arr = ["cat", "dog", "monkey"]
> arr.map { |e| e.upcase }
> # -> ["CAT", "DOG", "MONKEY"]
> arr
> # -> ["cat", "dog", "monkey"]
> arr.each { |e| e.upcase! }
> # -> ["CAT", "DOG", "MONKEY"]
> arr
> # -> ["CAT", "DOG", "MONKEY"]

It's basically the same, my version is just a shorthand :P


Daniel