# How to wrap either forkoff or map depending on a config variable?

**URL:** <https://www.ruby-forum.com/t/how-to-wrap-either-forkoff-or-map-depending-on-a-config-variable/137954>\
**Category:** Ruby\
**Created:** [May 18, 2008, 10:03pm UTC](https://www.ruby-forum.com/t/how-to-wrap-either-forkoff-or-map-depending-on-a-config-variable/137954 "2008-05-18T22:03:45Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shot\_SPiotr\_S.S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e79b87/32.png) [@Shot\_SPiotr\_S.S](https://www.ruby-forum.com/u/Shot_SPiotr_S.S)\
**Post date:** [May 18, 2008, 10:03pm UTC](https://www.ruby-forum.com/t/how-to-wrap-either-forkoff-or-map-depending-on-a-config-variable/137954/1 "2008-05-18T22:03:45Z")

</div>

Hello, good people of ruby-talk.

Iâ€™m trying to write an Enumerable#parallel method that, depending on  
a config option (retrieved inside it) would end up being an alias for  
either Enumerable#map or Enumerable#forkoff.

(I know calling enum.forkoff(1) should equal enum.map, but I need  
the wrapper to call #map, as forkoff doesnâ€™t work under JRuby.)

Iâ€™m quite new to the idea of blocks/closures, and while I love using  
them, Iâ€™m still not sure how to write such a method. What Iâ€™m looking  
for is something like this:

module Enumerable  
def parallel &block  
if Config.processes == 1  
# call map with the passed block  
else  
# call forkoff with the passed block  
end  
end  
end

Ideally, the call to forkoff would pass Config.processes as its  
first param â€“ i.e., calling enum.parallel {â€¦} would mean calling  
enum.forkoff(Config.processes) {â€¦}

– Shot

---

<div class="post-metadata">

**Author:** ![Shot\_SPiotr\_S.S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e79b87/32.png) [@Shot\_SPiotr\_S.S](https://www.ruby-forum.com/u/Shot_SPiotr_S.S)\
**Post date:** [May 18, 2008, 10:09pm UTC](https://www.ruby-forum.com/t/how-to-wrap-either-forkoff-or-map-depending-on-a-config-variable/137954/2 "2008-05-18T22:09:04Z")

</div>

Shot (Piotr S.):

> Iâ€™m trying to write an Enumerable#parallel method that, depending on  
> a config option (retrieved inside it) would end up being an alias for  
> either Enumerable#map or Enumerable#forkoff.

FWIW, the spec to pass is

describe Enumerable do  
it ‘should be able to process in parallel, depending on config option’  
do  
ArtDecomp::Config.processes = 1  
pid1, pid2 = [1,2].parallel { Process.pid }  
pid1.should == pid2  
ArtDecomp::Config.processes = 2  
pid1, pid2 = [1,2].parallel { Process.pid }  
pid1.should\_not == pid2  
end  
end

– Shot

---

<div class="post-metadata">

**Author:** ![Shot\_SPiotr\_S.S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e79b87/32.png) [@Shot\_SPiotr\_S.S](https://www.ruby-forum.com/u/Shot_SPiotr_S.S)\
**Post date:** [May 18, 2008, 10:19pm UTC](https://www.ruby-forum.com/t/how-to-wrap-either-forkoff-or-map-depending-on-a-config-variable/137954/3 "2008-05-18T22:19:04Z")

</div>

Shot (Piotr S.):

> Shot (Piotr S.):

> > Iâ€™m trying to write an Enumerable#parallel method that, depending on  
> > a config option (retrieved inside it) would end up being an alias for  
> > either Enumerable#map or Enumerable#forkoff.

> FWIW, the spec to pass is

> describe Enumerable do  
> it ‘should be able to process in parallel, depending on config option’ do  
> ArtDecomp::Config.processes = 1  
> pid1, pid2 = [1,2].parallel { Process.pid }  
> pid1.should == pid2  
> ArtDecomp::Config.processes = 2  
> pid1, pid2 = [1,2].parallel { Process.pid }  
> pid1.should\_not == pid2  
> end  
> end

Ok, a patch to make it actually test the implementation:

describe Enumerable do  
it ‘should be able to process in parallel, depending on config  
option’ do  
ArtDecomp::Config.processes = 1  
pid1, pid2 = [1,2].parallel { Process.pid }

- pid1.should == pid2

- pid1.should == Process.pid  
ArtDecomp::Config.processes = 2  
pid1, pid2 = [1,2].parallel { Process.pid }  
pid1.should\_not == pid2  
end  
end

– Shot (aware that the above spec in not really in true BDD spirit)

---

<div class="post-metadata">

**Author:** ![Shot\_SPiotr\_S.S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e79b87/32.png) [@Shot\_SPiotr\_S.S](https://www.ruby-forum.com/u/Shot_SPiotr_S.S)\
**Post date:** [May 19, 2008, 1:40am UTC](https://www.ruby-forum.com/t/how-to-wrap-either-forkoff-or-map-depending-on-a-config-variable/137954/4 "2008-05-19T01:40:49Z")

</div>

Hi,

To pass a block as a block to another function, put an ampersand before  
the  
variable name:

map &block  
forkoff &block

If you are interested in performance, know that using the &block  
notation  
for blocks is slower than using the block\_given? and yield semantics.

Dan

On Sun, May 18, 2008 at 4:03 PM, Shot (Piotr S.) [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Shot\_SPiotr\_S.S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e79b87/32.png) [@Shot\_SPiotr\_S.S](https://www.ruby-forum.com/u/Shot_SPiotr_S.S)\
**Post date:** [May 21, 2008, 6:07pm UTC](https://www.ruby-forum.com/t/how-to-wrap-either-forkoff-or-map-depending-on-a-config-variable/137954/5 "2008-05-21T18:07:57Z")

</div>

Daniel F.:

> To pass a block as a block to another function,  
> put an ampersand before the variable name

Thanks, this works perfectly now:

module Enumerable  
def parallel &block  
case ArtDecomp::Config.processes  
when 1 then map &block  
else forkoff ArtDecomp::Config.processes, &block  
end  
end  
end

(I should probably put it in a module and extend the  
relevant enums rather than monkeypatching Enumerableâ€¦)

> If you are interested in performance, know that using the &block  
> notation for blocks is slower than using the block\_given? and yield  
> semantics.

Thanks for the tip. In which cases does it matter? (In my very rough  
benchmarks it doesnâ€™t, but then the enum in question is rather small,  
while the blockâ€™s contents take relatively long time to compute.)

How would I implement the above using block\_given? + yield?

Sorry for being braindead here â€“ I implemented #every\_pair by wrapping  
#each twice, but Iâ€™m a bit stumbled on how to handle #mapâ€™s/#forkoffâ€™s  
returns; cache them in an array? I tried wrapping my mind around this  
but I still donâ€™t feel familiar enough in the block/yield territoryâ€¦  
How would I pass the (variable number of) blockâ€™s arguments through  
#parallel to the called methods? (I tried to come up with something  
using \*args but failed.)

– Shot

---

<div class="post-metadata">

**Author:** ![Shot\_SPiotr\_S.S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e79b87/32.png) [@Shot\_SPiotr\_S.S](https://www.ruby-forum.com/u/Shot_SPiotr_S.S)\
**Post date:** [May 21, 2008, 7:08pm UTC](https://www.ruby-forum.com/t/how-to-wrap-either-forkoff-or-map-depending-on-a-config-variable/137954/6 "2008-05-21T19:08:58Z")

</div>

Shot (Piotr S.):

> module Enumerable  
> def parallel &block  
> case ArtDecomp::Config.processes  
> when 1 then map &block  
> else forkoff ArtDecomp::Config.processes, &block  
> end  
> end  
> end

> How would I implement the above using block\_given? + yield?

It seems the below works:

module Enumerable  
def parallel  
case ArtDecomp::Config.processes  
when 1 then map { yield }  
else forkoff ArtDecomp::Config.processes { yield }  
end  
end  
end

– Shot
