May 21, 2021 Swift
Swift supports functional programming, which describes Swift's lazy computing.
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.
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.
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.
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 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 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")
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