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

ToAsync implemented: Issue #95 #505

Closed
wants to merge 1 commit into from
Closed

Conversation

akarnokd
Copy link
Member

Added 44 overloads of toAsync.

@cloudbees-pull-request-builder

RxJava-pull-requests #429 SUCCESS
This pull request looks good

@DavidMGross
Copy link
Collaborator

Can you help me understand the purpose of toAsync(Action)? Is it just that
you want to hold off on executing some hunk of code until some cascade of
observables is subscribed to and begins to fire, or is there more to it
than that?

On Wed, Nov 20, 2013 at 1:10 PM, CloudBees pull request builder plugin <
notifications@github.com> wrote:

RxJava-pull-requests #429https://netflixoss.ci.cloudbees.com/job/RxJava-pull-requests/429/SUCCESS
This pull request looks good


Reply to this email directly or view it on GitHubhttps://github.com//pull/505#issuecomment-28931217
.

David M. Gross
PLP Consulting

@akarnokd
Copy link
Member Author

@DavidMGross As I understand Rx.NET, it is something like this:

You have an action A, but you don't want to execute it now, so you wrap it into an Observable that runs on a background thread. Once some observer subscribes, the action gets executed on the background thread and a onNext(null) + onComplete() is issued to it. However, it uses an AsyncSubject internally, so the action A is executed only once, and its "result" retrievered instantly to late observers.

The value comes when you want to execute an action with certain parameter values. Given an Action1, that takes some parameter, you would make its execution asynchronous and you create a function for executing it with a particular parameter:

Action1<Integer> a1 = v -> lengthlyOperation(v);

Func1<Integer, Observable<Void>> async = Observable.toAsync(a1);

Observable<Void> o = async.call(1);
o.subscribe(() -> doSomethingWhenCompleted);
async.call(2).subscribe(() -> doSomethingForParam2());
// later
o.subscribe(() -> doSomethingWhenCompletedAgain());

In this example, you'll trigger an execution of a1 with value 1, and in parallel, a1 with value 2. Later, if you subscribe to "o" again, you would get an "instant" completion.

There are overloads for functions so you can get some result back as well.

This seems to be similar to making a Future into an Observable, but there are a bunch of overloads for multi-parameter actions and functions, not just a simple Callable and Runnable case.

@DavidMGross
Copy link
Collaborator

Thanks! Just what I needed.

On Wed, Nov 20, 2013 at 2:33 PM, akarnokd notifications@github.com wrote:

@DavidMGross https://github.com/DavidMGross As I understand Rx.NET, it
is something like this:

You have an action A, but you don't want to execute it now, so you wrap it
into an Observable that runs on a background thread. Once some observer
subscribes, the action gets executed on the background thread and a
onNext(null) + onComplete() is issued to it. However, it uses an
AsyncSubject internally, so the action A is executed only once, and its
"result" retrievered instantly to late observers.

The value comes when you want to execute an action with certain parameter
values. Given an Action1, that takes some parameter, you would make its
execution asynchronous and you create a function for executing it with a
particular parameter:

Action1 a1 = v -> lengthlyOperation(v);
Func1<Integer, Observable> async = Observable.toAsync(a1);
Observable o = async.call(1);o.subscribe(() -> doSomethingWhenCompleted);async.call(2).subscribe(() -> doSomethingForParam2());// latero.subscribe(() -> doSomethingWhenCompletedAgain());

In this example, you'll trigger an execution of a1 with value 1, and in
parallel, a1 with value 2. Later, if you subscribe to "o" again, you would
get an "instant" completion.

There are overloads for functions so you can get some result back as well.

This seems to be similar to making a Future into an Observable, but there
are a bunch of overloads for multi-parameter actions and functions, not
just a simple Callable and Runnable case.


Reply to this email directly or view it on GitHubhttps://github.com//pull/505#issuecomment-28938521
.

David M. Gross
PLP Consulting

@akarnokd akarnokd mentioned this pull request Nov 21, 2013
@benjchristensen
Copy link
Member

@headinthebox I'm wondering if these are better suited on a different class than Observable, similar to how we separated out BlockingObservable since many of these do not return Observable. In other words, are these worthy of having on Observable and increasing the surface area of the API significantly or can they live in another utility class?

@benjchristensen
Copy link
Member

The other problem is that many of these method overloads will not work for dynamic languages like Groovy and Clojure as the method arity is the same, only the type of Func being accepted is different and those can't be disambiguated by those languages.

For example: toAsync(Action0 action) and toAsync(Func0<R> func) are ambiguous.

We need to think through how to specify all of these in a way that is descriptive and usable and consciously understand impact on our polyglot principles.

@akarnokd
Copy link
Member Author

Perhaps:

rx.async.AsyncFunctions.fromFunc0(Func0)
rx.async.AsyncFunctions.fromFunc1(Func1<T1, R>)

rx.async.AsyncActions.fromAction0(Action0)
rx.async.AsyncActions.fromAction1(Action1)

I suggest the package rx.async instead of rx.util.functions as I'd rather avoid package cycles, unless we expect the "async" keyword in some future Java.

@headinthebox
Copy link
Contributor

Why not all call them Async(....) and use static import so you can write Async((Integer x)->x). Looks really nice.

@akarnokd
Copy link
Member Author

@headinthebox I think because of Groovy (and others) are unable to differentiate based on arity; I had to drop a few overloads of toMap and toMultimap because of this.

@benjchristensen
Copy link
Member

Yes, we can't have two overloads like this and still support non-strongly-typed languages:

async(Func1 f)
async(Func2 f)

Strongly typed languages can differentiate based on the number of args Func1 and Func2 take, but others like Groovy, Clojure (and most likely Javascript) can't.

@benjchristensen
Copy link
Member

We should try Java 8 Nashorn to determine how Javascript will behave with functional interfaces as that's going to be a major player on the JVM in the coming years.

@samuelgruetter
Copy link
Contributor

What about having both @headinthebox' and @akarnokd's solutions at the same time?

@benjchristensen
Copy link
Member

@headinthebox and I have reviewed this and feel the following is needed:

  • These should live in a separate class ... rx.util.functions.Async
  • The generics need covariance/contra-variance support added.
  • Let's retain the type-safe overloads but then probably need a asyncFunc(FuncN f) method for dynamic languages. This is not something we want done typically and definitely not in Observable but makes sense for this utility class so we don't penalize the strongly typed languages.

@akarnokd
Copy link
Member Author

Closing. See #533 for updated version.

@akarnokd akarnokd closed this Nov 27, 2013
@akarnokd akarnokd deleted the ToAsync branch January 13, 2014 10:05
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

Successfully merging this pull request may close these issues.

None yet

6 participants