Giter Club home page Giter Club logo

Comments (6)

mluisbrown avatar mluisbrown commented on July 16, 2024 1

Ok, I see. In that case, since your proposed solution could bring the API closer to the original TCA, it sounds like a great idea 😄

Do you want to create a PR with your draft solution?

Extend ReactiveSwift to use protocols // Maybe it's nice, but seems like a joke

That would be a massive undertaking, and probably not possible without a re-write!

Rewrite TCA to the OpenCombine

It's an option, but it should be for a separate fork. The benefit of this fork is not just that you can use iOS < 13, but that you can use ReactiveSwift, which is battle tested OSS project.

So your solution to use KeyPathContainers looks great 👍

from reactiveswift-composable-architecture.

maximkrouk avatar maximkrouk commented on July 16, 2024 1

Well I think I'll make a PR with an updated draft soon 🙂

from reactiveswift-composable-architecture.

maximkrouk avatar maximkrouk commented on July 16, 2024

I found one more, probably the best one, it is major too, but it won't cause logic inconsistency of any kind:

/// A producer of store state.
@dynamicMemberLookup
public struct Produced<Value>: SignalProducerConvertible { // <- here is a protocol conformance
    
    @dynamicMemberLookup
    public struct KeyPathContainer<LocalValue: Equatable>: SignalProducerConvertible { // <- here is a protocol conformance
        let produced: Produced<Value>
        let keyPath: KeyPath<Value, LocalValue>
        public var producer: Effect<LocalValue, Never> {
            produced.producer.map(keyPath).skipRepeats()
        }

        // this will resolve nested KeyPaths
        public subscript<T: Equatable>(dynamicMember keyPath: KeyPath<LocalValue, T>) -> KeyPathContainer<T> {
            KeyPathContainer<T>(produced: produced, keyPath: self.keyPath.appending(path: keyPath))
        }
    }

    public let producer: Effect<Value, Never>
    
    init(by upstream: Effect<Value, Never>) {
        self.producer = upstream
    }
    
    /// Returns the resulting producer of a given key path.
    public subscript<LocalValue: Equatable>(
        dynamicMember keyPath: KeyPath<Value, LocalValue>
    ) -> KeyPathContainer<LocalValue> {
        KeyPathContainer(produced: self, keyPath: keyPath)
    }
}

from reactiveswift-composable-architecture.

mluisbrown avatar mluisbrown commented on July 16, 2024

Hey @maximkrouk, sorry for the delay in replying.

In my use of TCA I haven't found the need for this feature yet. I'm not sure of the value of adding this to project, at least not at this point.

I would like to keep the API here as close as possible to the original TCA. Have you raised this issue on that repo also?

from reactiveswift-composable-architecture.

maximkrouk avatar maximkrouk commented on July 16, 2024

No problem, I use an extension to enable that API viewStore.producer(for: \.KeyPath<State, Value>) -> Produced<Value>, so the proposal does not block me 🙂

The original TCA uses Publisher protocol, thats why their StorePublisher supports nested publishers for properties and the use this type of API

StorePublisher.dynamicMember -> new StorePublisher

Here at RSCA we use

Published.dynamicMember -> Effect // SignalProducer

so we can't use dynamic keypaths for further traversal.

For the solution, we can

  1. Extend ReactiveSwift to use protocols // Maybe it's nice, but seems like a joke 😅
  2. Rewrite TCA to the OpenCombine // I find it interesting, but I do not have time to do that, also I'm not sure, that everithing works as expected in the framework
  3. Use KeyPathContainers // The easiest way for the implementation

For the third variant I wrote this draft. Also there is a chance, that if we add another overload for dynamicMemberKeypath which returns an Effect, we'll be able to make the API even closer to the original TCA.

//           ┌–  KeyPathContainer<State, Value> // Effect has no `nestedKeyPath` path so swift should handle it
producedState.keyPath.nestedKeyPath.assign(to: localKeyPath, on: object)
//                   └– Effect<NestedValue, Never> // KeyPathContainer has no `assign` method so swift should handle it

Once again, now out-of-the-box we have to do that to do the same:

//           ┌–  Effect<State, Never> // Effect has no dynamicMember subscripts 
producedState.keyPath.map(\.nestedKeyPath).skipRepeats().assign(to: localKeyPath, on: object)

from reactiveswift-composable-architecture.

mluisbrown avatar mluisbrown commented on July 16, 2024

Resolved by #28

from reactiveswift-composable-architecture.

Related Issues (8)

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.