Coder Social home page Coder Social logo

Comments (16)

jspahrsummers avatar jspahrsummers commented on April 17, 2024

RACUnit.defaultUnit is equivalent to sendCompleted. Most of the framework's current uses of RACUnit could easily be replaced with something else, like nil or a dummy value.

Alternatively, nil could be equivalent to sending completed. nil values aren't handled very well right now anyways (e.g., in -merge), and this would lead to a more natural translation between subscribables and collections/sequences.

from reactivecocoa.

jonsterling avatar jonsterling commented on April 17, 2024

Hmmm.... I do like the idea of having a single stream of values.

The biggest win that can come out of this is providing some common interfaces of well-understood abstraction that makes sense for both subscribables and sequences of all kinds.

I'm sure at this point I sound quite like a broken record on this matter, and I've little doubt you've heard my thoughts on this before. Nonetheless, Functors and Idioms may be modeled in Objective-C very nicely using HOMs, with a little bit of care; RAC lends itself beautifully to the following kind of API:

id nameStream = self.nameField.rac_textSubscribable;
id ageStream = self.ageField.rac_textSubscribable;
id personStream = [Person.idiom name:nameStream age:ageStream]; 

// We can use the same +idiom machinery with any other kind of "sequence"
id names = @{ @"Joseph", @"James", @"Tucker", @"Tyrone" };
id ages = @{ @14, @63, @7, @16 };
id people = [Person.idiom name:names ages:ages];

The real trick here is to write the same code over reactive streams and sequences; RAC has heretofore lent itself to a pretty "RAC-heavy" coding style, if you catch my drift. It would be nice to liberate our semantics from this prison of specificity, as it were, into something much more general: a family of abstractions suitable for sequences of any sort.

from reactivecocoa.

joshaber avatar joshaber commented on April 17, 2024

Rx has Materialize/Dematerialize methods that sound very similar to what you're proposing.

If we implement something like those, it seems like we get all the upsides you're talking about without big, breaking changes.

Like we talked about last weekend, I'm not opposed to drastically changing RAC if we can convince ourselves of better semantics.

from reactivecocoa.

jspahrsummers avatar jspahrsummers commented on April 17, 2024

That could work, although it'd be a huge pain in the ass to conditionalize stuff based on whether the stream is materialized or not.

For instance, if I want to use repeat, it either has to know about materialization, or I have to make sure to dematerialize before I invoke repeat and then rematerialize after.

Also, sidenote: I'm getting really sick of typing "materialize."

from reactivecocoa.

anaisbetts avatar anaisbetts commented on April 17, 2024

Monadic bind could be applied to subscribables.

Bind can already apply to Subscribables, at least in Rx, it's actually a huge part of using Rx; you just need to implement it. I'll give you the secrets, in C#, you can translate :)

// This is a method that, given a Subscribable, for each item in the Subscribable, returns a new Subscribable
// So! For an input [1,2,3,4], you get an output of [IO(1), IO(2), IO(3), IO(4)], but then it returns the results
// of "flattening" that Subscribable
IObservable<TOut> SelectMany(IObservable<TIn> input, Func<TIn, IObservable<TOut>> selector);

So, to implement this, a way to think of it is:

IObservable<T> Merge(IObservable<IObservable<T>> sequenceOfSequences);

IObservable<TOut> SelectMany(IObservable<TIn> input, Func<TIn, IObservable<TOut>> selector)
{
    IObservable<IObservable<TOut>> selectedSequence = input.Select(selector);
    return Merge(selectedSequence);
}

Merge takes a Subscribable of Subscribables, subscribes to all of them that come over the wire, and every item that comes through, it emits it to the output.

If none of this makes any kind of sense, let me know and I can elaborate :)

from reactivecocoa.

jspahrsummers avatar jspahrsummers commented on April 17, 2024

We do have selectMany in RAC, but it's not truly a bind unless we have something like Materialize – which, as noted above, has its own problems.

from reactivecocoa.

anaisbetts avatar anaisbetts commented on April 17, 2024

Why is it not truly a bind?

from reactivecocoa.

jspahrsummers avatar jspahrsummers commented on April 17, 2024

So, let me back up a bit and explain the concept I have in my mind.

I'd love to have RACSequence and RACSubscribable as two distinct things, which share a monadic interface that can be used to implement most of the operations that are subscribable-specific right now.

For instance:

@concreteprotocol(RACMonad)

- (instancetype)filter:(BOOL (^)(id))filterBlock {
    return [self bind:^(id value) {
        if (filterBlock(value)) {
            return [self.class unit:value];
        } else {
            return [self.class empty];
        }
    }];
}

@end

I think I did that right.

Looking at that implementation, though, I guess subscribables don't actually need to change to make it work. It's still a little weird to me that errors and completion can't be handled from within the function being bound, but I guess that's no different from Either or Maybe in Haskell.

from reactivecocoa.

jspahrsummers avatar jspahrsummers commented on April 17, 2024

@jonsterling Do you have a reply to the above? I think that mostly resolved my concerns with error/completed, but maybe there's a case I'm missing.

from reactivecocoa.

jspahrsummers avatar jspahrsummers commented on April 17, 2024

Yeah, KVO is a great point that I hadn't even considered.

from reactivecocoa.

Coneko avatar Coneko commented on April 17, 2024

Whoops, deleted the comment by mistake. I'll rewrite it, the above reply was to my comment.

Alternatively, nil could be equivalent to sending completed. nil values aren't handled very well right now anyways (e.g., in -merge), and this would lead to a more natural translation between subscribables and collections/sequences.

I don't think that's a good idea. Bridging RAC to KVO is a great way to mix RAC and non-RAC code, and for KVO nil is a valid value for keypaths. (cf. #82)

I think the sentinel value for completed should be a singleton object with only that purpose, so users of the library wouldn't have to wrap a certain value or avoid using it entirely because it was overloaded with a new meaning.
I like RACTuple's handling of nil better than NSArray's.

from reactivecocoa.

jonsterling avatar jonsterling commented on April 17, 2024

Still digesting :)

Sent from my iPhone

On Oct 31, 2012, at 4:43 PM, Justin Spahr-Summers [email protected] wrote:

@jonsterling Do you have a reply to the above? I think that mostly resolved my concerns with error/completed, but maybe there's a case I'm missing.

β€”
Reply to this email directly or view it on GitHub.

from reactivecocoa.

Coneko avatar Coneko commented on April 17, 2024
id<RACSubscribable>a = [RACSubscribable error:error];
id<RACSubscribable>b = [RACSubscribable return:value];
id<RACSubscribable>c = [RACSubscribable empty];

id<RACSubscribable>combined = [RACSubscribable combineLatest:@[a, b, c]];

With error and completed not "out of band", does combined send (error, value, completed) rather than just error? It would make using +combineLatest pretty bothersome.

Wouldn't it be better to treat sequences as subscribables rather than the other way around?

from reactivecocoa.

jspahrsummers avatar jspahrsummers commented on April 17, 2024

@Coneko No, combined would error before anything else is sent, without violating the above semantics.

That said, I think @xpaulbettsx has convinced me this isn't really necessary, and either can be represented as the other. We can talk more about subscribables and sequences in #89, though, since this thread is winding down.

from reactivecocoa.

Coneko avatar Coneko commented on April 17, 2024

I realized what you were trying to say with the snippet of code.
There's no need to think about one as the other at all to begin with.
Since they're both monads, new methods can be shared between the two as long as you only use methods you define on monads to implement them.

It took me a while to figure out because I was silly and didn't notice bind and >>= were the same thing.

Given all that, I think the idea of adding sequences to ReactiveCocoa is great from all points of view. Although keeping this up might turn ReactiveCocoa into FunctionalCocoa.

from reactivecocoa.

jspahrsummers avatar jspahrsummers commented on April 17, 2024

🀘:feelsgood:πŸ‘

from reactivecocoa.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.