Does Swift's standard library include a list anamorphism for a Sequence
or something similar?
An Anamorphism on lists or sequences would be the opposite of the reduce
function. So instead of collapsing a sequence down to a single value, it will build a sequence up.
reduce
takes an initial value, and a function for combining sequence elements with this, and returns a final value. It's signature looks like this (newlines added for readability):
public func reduce<Result>(
_ initialResult: Result,
_ nextPartialResult: (Result, Self.Element) throws -> Result) rethrows
-> Result
An anamorphism for sequence might go like this:
func inflate<State, Element>(
_ initialState: State,
_ generator: @escaping (State) -> (State, Element)?)
-> AnamorphismSequence<State, Element>
By giving it some initial state, and telling it how to turn that in to an element and the next state, it can build up a sequence for you. So, I could get an array such as Array(1..<10)
like this:
Array(inflate(1) { s in s < 10 ? (s+1, s) : nil })
Swift has two variants of this. Both types have private initializers, but they can instead be generated using their respective global functions.
UnfoldSequence<Element, State>
, which is produced bysequence(state:next:)
UnfoldFirstSequence<Element>
which is produced bysequence(first:next:)
The latter doesn't do anything that can't be done by the former. It's merely a simplified version, that's used when you don't need a separate state, beyond merely knowing what the previous element was.
Here's how your
1..<10
example can be implemented, using both methods:Your example is better suited to the simpler
sequence(first:next:)
. The latter would be more useful for something like a sequence that yields perfect squares: * Your maintained state would be the squares of the perfect squares (which increment by 1 with every unfold) * Your sequence yields it elements by multiplying that state by itself (to square it)Technically, you could use a captured local variable to emulate the state of an
UnfoldSequence
, but that's quite a bit messier, and almost certainly slower.