Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Swift functional programming Lazy calculation


May 21, 2021 Swift


Table of contents


Swift Functional Programming - Lazy Computing

Swift supports functional programming, which describes Swift's lazy computing.

Lazy calculation

Lazy computing is a feature of functional programming languages. W hen using lazy evaluation, an expression is evaluated not immediately after it is bound to a variable, but when the value is taken. Lazy computing has the following advantages:

  • First, you can use them to create an infinite sequence of such a data type. Because values are not calculated until needed, you can simulate infinite sequences with lazy collections.

  • Second, storage space is reduced. B ecause calculations only occur when they are really needed. As a result, unnecessary storage space is saved.

  • Third, reduce the amount of computation to produce more efficient code. B ecause calculations only occur when they are really needed. For example, look for the first value in an array that meets a certain criterion.

In purely functional programming languages, such as Haskell, lazy values are performed by default. T herefore, Haskell is called an inert language. I n contrast to most programming languages, such as Java, the value of C+ is strict, or early. S wift defaults to strict evaluation, i.e. every expression needs to be evaluated, regardless of whether the expression actually needs to be evaluated in practice. However, Swift, as a programming language that supports a variety of paradigms, also provides syntax to support lazy learning.

Built-in lazy function

In Swift, if inert computation is required, a sequence is explicitly converted into an inert sequence. T he conversion method is to use Swift's built-in lazy function. I t has four overloaded implementations. The compiler will choose the most correct implementation for you.

If it's Sequence (the class or structure that implements the SequenceType protocol), it returns LazySequence and if you pass in a Collection (the class or structure that implements the CollegeType protocol), it's LazyForwardCollection College, LazyBidirectionalCollection or LazyRandomAccessCollection Here is a functional prototype of the four function overload functions of the lazy function:

func lazy<S: SequenceType>(s: S) -> LazySequence<S>
func lazy<S: CollectionType where S.Index: ForwardIndexType>(s: S) -> LazyForwardCollection<S>
func lazy<S: CollectionType where S.Index: BidirectionalIndexType>(s: S) -> LazyBidirectionalCollection<S>
func lazy<S: CollectionType where S.Index: RandomAccessIndexType>(s: S) -> LazyRandomAccessCollection<S>

If an Array is passed in, it will return LazyRandomAccessCollection type. L azyRandomAccessCollection is an inert collection. Here's an example of turning Array into an inert sequence:

let r = 1...3
let seq = lazy(r).map {
    (i: Int) -> Int in
    println("mapping \(i)")
    return i * 2
}

for i in seq {
    println(i)
}

You'll get the following results:

mapping 1
2
mapping 2
4
mapping 3
6

This shows that seq is an inert sequence. Its value is calculated only when needed.

Generator

In Swift, Generator is any class or structure that implements the Generator Type protocol. G enerator can be understood as a sequence generator. The GeneratorType protocol requires defining an Element called Element and implementing a next method.

The GeneratorType protocol is implemented as follows:

protocol GeneratorType {
    typealias Element
    mutating func next() -> Element?
}

The typealias Element that the class implementing this protocol must define an alias called Element, which in part implements the generic protocol. The protocol also requires next the next function, whose return value is the Element type defined in the Element which represents the next element to be generated by the generator.

The following code implements a Fiponachi number column generator:

class FibonacciGenerator : GeneratorType {

    var current = 0, nextValue = 1  

    typealias Element = Int

    func next() -> Element? {
        let ret = current
        current = nextValue
        nextValue = nextValue + ret
        return ret
    }
}

The following code prints out 10 Fibonachi columns to show how to use the generator:

var n = 10
var generator = FibonacciGenerator()
while n-- > 0 {
    println(generator.next()!)
}

Generator is the foundation of Sequence and College.

Sequence

Sequence is any class or structure that implements the SequenceType protocol. S equence can be understood as a sequence. The SequenceType protocol requires the definition of an alias called Generator, type GeneratorType, and the implementation of a function that returns the generator Generator.

The SequenceType protocol is as follows:

protocol SequenceType : _Sequence_Type {
    typealias Generator : GeneratorType
    func generate() -> Generator
}

Similar to the GeneratorType protocol, typealias Generator : GeneratorType that the class implementing this protocol must define an alias called TheGenerator type GeneratorType. T he protocol also requires the implementation of generate which returns a Generator which should implement the GeneratorType protocol mentioned above. This means that Sequence actually contains a class that generates the Generator function.

The following code implements a Fiponachi number column using the Fibonachi number column generator mentioned above:

class FibonacciSequence: SequenceType
{
    typealias GeneratorType = FibonacciGenerator

    func generate() -> FibonacciGenerator {
        return FibonacciGenerator()
    }
}

The following code prints 10 Fiponachi series to show how to use the sequence:

let fib = FibonacciSequence().generate()
for _ in 1..<10 {
    println(fib.next()!)
}

Sequences that conform to SequenceType have the potential to become lazy sequences. The way to become an lazy sequence is to call the lazy function on which it appears:

let r = lazy(stride(from: 1, to: 8, by: 2))

The function stride returns StrideTo which is Sequence. Therefore, the lazy function returns lazySequence object.

Collection

Collection is a class or structure of protocols that implement the CollegeType protocol. T he CollectionType protocol inherits the SequenceType protocol. So Collection also implemented SequenceType, which is also Sequence.

The CollectionType protocol is as follows:

protocol _CollectionType : _SequenceType {
    typealias Index : ForwardIndexType
    var startIndex: Index { get }
    var endIndex: Index { get }
    typealias _Element
    subscript (_i: Index) -> _Element { get }
}

protocol CollectionType : _CollectionType, SequenceType {
    subscript (position: Self.Index) -> Self.Generator.Element { get }
}

Therefore, the CollectionType protocol first implements the SequenceType protocol and subscript to get the element values for each location in the sequence.

In Swift, a number of built-in classes such as Dictionary, Array, Range, and String implement the ActionType protocol. As a result, most of Swift's container classes can become lazy sequences.

// a will be a LazyRandomAccessCollection
// since arrays are random access
let a = lazy([1,2,3,4])

// s will be a LazyBidirectionalCollection
let s = lazy("hello")

Summarize

The collection data structure in Swift is strictly valued by default. H owever, Swift also provides lazy syntax, which you need to explicitly declare when you need inertness. This provides the conditions for developers to use inertia in Swift.

Original origin: Http://lincode.github.io/Swift-Lazy
Author: Lin Guo