Быстрый анаморфизм последовательности

Есть ли в стандартной библиотеке Swift анаморфизм списка для Sequence или что-то подобное?

Анаморфизм в списках или последовательностях будет противоположностью reduce функция. Таким образом, вместо свертывания последовательности до одного значения, она будет создавать последовательность вверх.

reduce принимает начальное значение и функцию для объединения элементов последовательности с этим и возвращает конечное значение. Его подпись выглядит следующим образом (для удобства чтения добавлены новые строки):

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 })

1 ответ

Решение

У Swift есть два варианта этого. Оба типа имеют частные инициализаторы, но вместо этого они могут быть сгенерированы с использованием их соответствующих глобальных функций.

  1. UnfoldSequence<Element, State>, который производится sequence(state:next:)

  2. UnfoldFirstSequence<Element> который производится 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, но это немного более грязно, и почти наверняка медленнее.

Другие вопросы по тегам