Object#tap (was Nice algorithm for 'spreading' indexes across an array?)

On Wed, Sep 2, 2009 at 1:41 AM, Max
Williams[email protected] wrote:

arr = (1…12).to_a
It feels like there should be a simple solution for this but i can’t
think of a nice way. Anyone?

thanks
max

Thanks to a post by David M. in a recent thread, I learned about
Object#tap.
He used it on a hash.

I’ve used it here on an array.
Is there any problem using Object#tap in this way?
I saw some examples, but in the examples the object was not modified
in the block.

class Array
def spread(n)
dup.tap{|a| (size-n).downto(1).map{|b| size*b/(size-n+1)}.each{|c|
a.delete_at(c)}}
end
end

arr = (1…12).to_a
(3…12).each{|t| p arr.spread(t)}

###Output

[1, 6, 12]
[1, 4, 8, 12]
[1, 3, 6, 9, 12]
[1, 3, 5, 8, 10, 12]
[1, 2, 4, 6, 8, 10, 12]
[1, 2, 4, 6, 7, 9, 11, 12]
[1, 2, 3, 5, 6, 8, 9, 11, 12]
[1, 2, 3, 4, 6, 7, 8, 10, 11, 12]
[1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

Harry

On Wednesday, July 28, 2010 09:03:18 am Harry K. wrote:

Is there any problem using Object#tap in this way?
I saw some examples, but in the examples the object was not modified
in the block.

Oh, you mean modifying the array?

class Array
def spread(n)
dup.tap{|a| (size-n).downto(1).map{|b| size*b/(size-n+1)}.each{|c|
a.delete_at©}}
end
end

Not particularly. The thing you have to be careful of is reassigning it
– for
example, this wouldn’t work:

1.tap {|x| x+=1}

You have to actually modify the object. For example, if we’re talking
about
arrays, instead of this:

string.tap {|x| x + ‘foo’}

Do this:

string.tap {|x| x << ‘foo’}

It seems like << returns self, so that’s completely unnecessary, you
could
just do this:

(string << ‘foo’)

…but hopefully it illustrates the point.

I have a feeling I’m overcomplicating things, though. Here’s one
possible
implementation of Object#tap:

class Object
def tap
yield self
self
end
end

Nothing mysterious about it at all. (MRI might do it in C, I’m not sure,
but
the above works.)

On Thu, Jul 29, 2010 at 12:40 PM, David M. [email protected]
wrote:

Do this:

string.tap {|x| x << ‘foo’}

A nice use of #tap (IMO, and these things are very much a matter of
opinion):

message = String.new.tap { |s|
s << “…”
s << “…”
if some_condition?
s << “…”
else
s << “…”
end
end

Gavin