Swift 序列变形

Swift Sequence Anamorphism

Swift 的标准库是否包含用于 Sequence 或类似内容的 list anamorphism

列表或序列上的变形与 reduce 函数相反。因此,它不会将序列折叠成单个值,而是向上构建序列。

reduce 取一个初始值,以及一个将序列元素与此组合的函数,returns 取一个最终值。它的签名看起来像这样(为了便于阅读而添加了换行符):

public func reduce<Result>(
  _ initialResult: Result, 
  _ nextPartialResult: (Result, Self.Element) throws -> Result) rethrows
  -> Result

序列的变形可能是这样的:

func inflate<State, Element>(
  _ initialState: State, 
  _ generator: @escaping (State) -> (State, Element)?)
  -> AnamorphismSequence<State, Element>

通过给它一些初始状态,并告诉它如何将其转换为一个元素和下一个状态,它可以为您构建一个序列。所以,我可以得到一个数组,例如 Array(1..<10) 这样的:

Array(inflate(1) { s in s < 10 ? (s+1, s) : nil })

Swift 有两个变体。两种类型都有私有初始化器,但它们可以使用各自的全局函数生成。

  1. UnfoldSequence<Element, State>, which is produced by sequence(state:next:)

  2. UnfoldFirstSequence<Element> which is produced by sequence(first:next:)

前者做不到的,后者不做。它只是一个简化版本,当您不需要单独的状态时使用,而不仅仅是知道前一个元素是什么。

以下是您的 1..<10 示例的实施方式,使用两种方法:

Array(sequence(first: 1) { i in (i < 9) ? (i + 1) : nil })

Array(sequence(state: 1) { state -> Int? in 
    defer { state += 1 }
    return state < 10 ? state : nil
})

您的示例更适合更简单的 sequence(first:next:)。后者对于生成完美正方形的序列之类的东西更有用: * 您的维护状态将是完美正方形的正方形(每次展开都会增加 1) * 您的序列通过将该状态乘以自身(对其进行平方)来生成元素

从技术上讲,您可以使用捕获的局部变量来模拟 UnfoldSequence 的状态,但这有点混乱,而且几乎肯定会更慢。