Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#.find #273

Open
kochd opened this issue Jan 16, 2020 · 10 comments
Open

#.find #273

kochd opened this issue Jan 16, 2020 · 10 comments

Comments

@kochd
Copy link

kochd commented Jan 16, 2020

I got a expensive calculation and i want to kill all childs once one of them delivers a result:

results = Parallel.find(1..32, in_processes: 32) do
  this_could_take_long(1, 2)
end
p results #=> ["solution"]

Use case is solving a proof of work. One of the 16 processes will be the fastest and only one solution is needed. There seams to be no way to this or is ?

@grosser
Copy link
Owner

grosser commented Jan 16, 2020

check how Parallel.any? is implemented ... .find should be very similar ...

@grosser
Copy link
Owner

grosser commented Jan 16, 2020

... not sure if it's actually being lazy though ... there is support to raise Parallel::Break, just not sure how to also get the returned value ... that could be stored in the exception though, like raise Parallel::Break, result

@ellcs
Copy link

ellcs commented Oct 6, 2020

I've made an implementation. It's a bit hacky and would be happy to get some feedback. Before i make a pull request, i'd like to mention that Enumerable#find does actually not return the result, but the found element. So we need another name. While scrolling through the Array Documentation and Enumerable Documentation i did not find a matching name.

What do you think about the following names:

block = lambda { |e| if e > 2; e; end }
Parallel.first_result([1,2,3], &block) 
Parallel.find_first_result([1,2,3], &block) 
Parallel.first_done([1,2,3], &block) 

ellcs added a commit to ellcs/parallel that referenced this issue Oct 6, 2020
In addtion to Parallel::Kill and Parallel::Break, a new Exception class
named Parallel::Return allows raising an Exception which wraps a result
value. That wrapped result will be unwrapped.

When a method expects a single result, the option `:return_one` must be
provided, because a given Enumeration might not contain a matching element or
result.
ellcs added a commit to ellcs/parallel that referenced this issue Oct 6, 2020
In addtion to Parallel::Kill and Parallel::Break, a new Exception class
named Parallel::Return allows raising an Exception which wraps a result
value. That wrapped result will be unwrapped.

When a method expects a single result, the option `:return_one` must be
provided, because a given Enumeration might not contain a matching element or
result.
@grosser
Copy link
Owner

grosser commented Oct 7, 2020

usually this is done with [1,2,3].find { |x| break x if x.even? } so let's implement that inferface :)

@ellcs
Copy link

ellcs commented Oct 7, 2020

I don't want to start a dicussion, but... :)

I have some thoughts on your suggested interface [1,2,3].find { |x| break x if x.even? }:

  • The break x does not return x as you can see in the example below. It still returns the found element. So you actually do not need the break in the block and it has the same functionallity as { |x| x.even? }.
    block = lambda { |x| break(x*9) if x > 5 }
    (1..10).find(&block)
    # => 6
  • find is not intended to return the calculated value, but the element. Using that method name could lead to confusion.
  • I've implemented Rubys find aswell, but it returns the matching element, not the result. Have a look at 21b385e.

@grosser
Copy link
Owner

grosser commented Oct 8, 2020

(1..10).find { break 111 } works though 🤷

@grosser
Copy link
Owner

grosser commented Oct 8, 2020

... I guess the break might not be usable from inside parallel :/

@grosser
Copy link
Owner

grosser commented Oct 8, 2020

lib/parallel.rb:445:in fork': unexpected break`
yeah :(

@grosser
Copy link
Owner

grosser commented Oct 8, 2020

find_result sounds the best to me 👍

@grosser
Copy link
Owner

grosser commented Oct 8, 2020

... but breaking with a value could also be simple

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants