Generators with generators and sequences in Swift

I have a pretty good understanding of OO and Swift programming, but one area that really leaves me stuck is Generators and Sequences (I'm fine with the concept of protocols by the way).

For example, I performed this exercise from the Swift guide (Apple)

"EXPERIMENT Modify the anyCommonElements function to create a function that returns an array of elements that have two different sequences.

Inclusion of this:

func​ ​anyCommonElements​ <​T​, ​U​ ​where​ ​T​: ​SequenceType​, ​U​: ​SequenceType​, ​T​.​Generator​.​Element​: ​Equatable​, ​T​.​Generator​.​Element​ == ​U​.​Generator​.​Element​> (​lhs​: ​T​, ​rhs​: ​U​) -> ​Bool​ { for​ ​lhsItem​ ​in​ ​lhs​ { for​ ​rhsItem​ ​in​ ​rhs​ { if​ ​lhsItem​ == ​rhsItem​ { return​ ​true } } } return​ ​false } 

In it:

 func anyCommonElements <T, U where T: SequenceType, U: SequenceType, T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element> (lhs: T, rhs: U) -> [T.Generator.Element]? { var commonElements:[T.Generator.Element]? = nil for lhsItem in lhs { for rhsItem in rhs { if lhsItem == rhsItem { if (commonElements == nil) { commonElements = [] //init the array if not already } commonElements?.append(lhsItem) //add matching item to the array } } } return commonElements? //return nil or array of matched elements } 

I am pleased with the solution I wrote and it works well, including an optional return, however I am lost as to why the return type of the commonElements array should be this :

 var commonElements:[T.Generator.Element] 

Instead of this:

 var commonElements:[T] 

I read a fair cue ball on this issue, including:

https://schani.wordpress.com/2014/06/06/generators-in-swift/

http://robots.thoughtbot.com/swift-sequences

http://natashatherobot.com/swift-conform-to-sequence-protocol/

But I'm still completely lost - can someone please explain this in simple language or just a little abstract and not easy to describe?

It would be very nice, thanks, John

+5
source share
2 answers

T is the type of sequence. For simplicity, we take a special and familiar case and say that T is an array.

Then the type of thing contained in the array is T.Generator.Element . This is due to how the structure of the array is determined. Keep in mind that the array is shared. This is a SequenceType, which is a (generic) protocol with an empty type alias generator, which is limited to the GeneratorType type, which, in turn, is a (generic) protocol that has an empty type alias element. When generic is specialized, these empty type aliases are "populated" with the actual type. All sequences are like that. Therefore, if T is an array, then T.Generator.Element means "the actual type of these array elements."

So [T.Generator.Element] means "an array of the same type as the original elements of the array.

Your suggested expression, [T] , will mean an array of arrays, which we don't want.

Ok, now generalize T to any sequence (array, character string, etc.), and this explanation continues to work.

+12
source

Author's answer is no longer valid for the latest version of Swift. Here is an update compatible with version 3.0.1, they have simplified the creation of a common array. note: I originally used [Any] arrays, but updated the code based on the feedback below.

 func showCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> [T.Iterator.Element] where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element { var result:[T.Iterator.Element] = [] for lhsItem in lhs { for rhsItem in rhs { if lhsItem == rhsItem { result.append(lhsItem) } } } return result } 

You can test the code with the following commands:

 showCommonElements([1, 2, 3, 4, 5], [4, 7, 3]) showCommonElements(["apple", "banana", "orange", "peach"], ["orange", "pear", "apple"]) 
+1
source

Source: https://habr.com/ru/post/1211184/


All Articles