[Facets] Array#send_to_each

D

Daniel Schierbeck

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
 
V

Vincent Foley

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/download.htm
 
S

shortcutter

Vincent said:
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:
SyntaxError: compile error
(irb):2: syntax error
Object.new % 1,3
^
from (irb):2
from :0

Kind regards

robert
 
R

Ross Bamford

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"]
 
D

Daniel Schierbeck

Vincent said:
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
 
D

Daniel Schierbeck

Ross said:
... 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
 
G

Gavin Sinclair

Daniel said:
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
 
D

Daniel Schierbeck

Gavin said:
Daniel said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
474,206
Messages
2,571,068
Members
47,674
Latest member
scazeho

Latest Threads

Top