ACC
ACC

Reputation: 2570

Append to an array in Ruby

I am trying to use the parallel gem in ruby to call a function on each element of an array

require 'parallel'

arr = %w[one two three four five]
result ||= []    
Parallel.each(arr) do |elem|
  result << Random.rand(10)
end

But, when I run this, the result array is always empty. Why does it not append? It behaves the same way when result is a ruby Queue

Upvotes: 1

Views: 934

Answers (3)

Agis
Agis

Reputation: 33646

Each << operation happens in its own separate process (ie. in parallel) and so it's mutating a different result variable.

This happens because Parallel forks processes and forked processes have their own memory.

Upvotes: 1

Matt
Matt

Reputation: 20796

Pass in a :in_threads option:

require 'parallel'

arr = %w[one two three four five]
result ||= []
Parallel.each(arr, :in_threads => 8) do |elem|
  result << Random.rand(10)
end

Don't ask me to explain this in detail; I was just looking through the source code for the Parallel project and saw this as a possibility and tried it.

My guess is that it tells the threads to run as threads so that that they can share the result variable, rather than running as separate processes. But that's just a guess.

Upvotes: 2

Alex.Bullard
Alex.Bullard

Reputation: 5563

It doesn't append b/c Parallel forks into subprocesses that no longer share the same reference to result. In this case, one option might be to use Parallel.map and append the resulting array to result, ie

result ||= []    
result += Parallel.map(arr) { |elem| Random.rand(10) }

Upvotes: 2

Related Questions