【问题标题】:'Unfold' in Swift's Combine FrameworkSwift 组合框架中的“展开”
【发布时间】:2020-12-21 09:38:45
【问题描述】:

我正在寻找一种方法,可以让您对先前的输出做出反应以创建新的流。

它类似于scan,但不是返回一个输出,而是返回另一个发布者来发布下一个结果。

这是类似于扫描示例的内容:

func next(x: Int) -> AnyPublisher<Int?, Never> {
    return Future { x < 5 ? $0(.success(x + 1)) : $0(.success(nil)) }
}

next(0)
    .fold { x != nil ? next(x) : nil }
    .collect()
// Yields [1, 2, 3, 4]

更真实的东西:

paginated(0)
    .fold(limit: 100) { $0.index < $0.total ? paginated($0.index + 1) : nil  }
    .collect()
// Yields all pages as an array

【问题讨论】:

    标签: swift functional-programming reactive combine


    【解决方案1】:

    听起来您正在寻找“展开”操作。拥有一个接受某种状态并产生输出 + 下一个状态的函数,它可以从单个状态产生一系列输出。

    详情请看:https://nabilhassein.github.io/blog/unfold/

    虽然不知道如何在 Swift 中做到这一点。

    【讨论】:

    【解决方案2】:

    我最终实现了一些我自己现在或多或少满意的东西:

    func unfold(limit: Int = -1, _ fun: @escaping (Output) -> AnyPublisher<Output, Failure>?) -> Publishers.FlatMap<AnyPublisher<Output, Failure>, AnyPublisher<Output, Failure>> {
        flatMap { value -> AnyPublisher<Output, Failure> in
            let justPublisher = Just(value).mapError { $0 as! Failure }
            
            guard limit != 0, let publisher = fun(value) else {
                return justPublisher.eraseToAnyPublisher()
            }
            return justPublisher.append(publisher.fold(limit: limit - 1, fun)).eraseToAnyPublisher()
        }
    }
    

    不过,我非常愿意接受有关变体方法的建议!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-04
      • 1970-01-01
      相关资源
      最近更新 更多