Unifying interfaces LazySequence<T> and LazyFilteredSequence<T> in Swift

Viewed 34

While implementing custom filtering values I has encountered the problem. It is appeared when I tried to combine results from filtered and not-filtered LazySequences.

Here is sample to illustrate the problem:

let queryModulus: Int? = 10 // Sometimes may be **nil**
let values = [1, 2, 3, 4, 5, 6].lazy // Actually comes from **external** source

let filteredValues = queryModulus.map { modulus in 
    values.filter { $0 % modulus == 0 } 
} ?? values // Error appears on this statement

When compiling above snippet compiler gives me error:

.code.tio.swift:4:59: error: cannot convert value of type 'LazyFilterSequence<[Int]>' to closure result type 'LazySequence<[Int]>'
let filteredValues = queryModulus.map { modulus in values.filter { $0 % modulus == 0 } } ?? values // Error appears on this statement
                                                   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/srv/wrappers/swift4: line 5: ./.bin.tio: No such file or directory

The question is how to combine results of two expressions?

  • filtered one queryModulus.map { modulus in values.filter { $0 % modulus == 0 } } that has type LazyFilterSequence<[Int]>?
  • initial one values with type LazySequence<[Int]>

With quick research I realized that error appears on any collection. It means that LazySequence<T> and LazyFilteredSequence<T> is incompatible for Set, and others.

You can try.it

1 Answers

You simply need to add .lazy to the .filter inside your .map and then the return type of your .map and values will be identical.

let filteredValues = queryModulus.map { modulus in
    values.filter { $0 % modulus == 0 }.lazy
} ?? values

If you have a Set.lazy for your values, in your map, you first need to convert the result of filter to a new Set and then call lazy on that.

let setValues = Set([1, 2, 3, 4, 5, 6]).lazy
let filtered2 = queryModulus.map { mod in Set(setValues.filter { $0 % mod == 0}).lazy } ?? setValues
Related