What type should you use if you want to use index.advanceBy?

I wanted to find some objects next to another object in the array. I thought I could write such an extension method, but I get this error:

// Error: Cannot invoke 'advanceBy' with an argument list of type '(Int)'

The type is Intclearly erroneous, but the method indexOftakes an argument Self.Distance, and I'm not sure how to use it as a parameter type.

extension CollectionType where Generator.Element : Equatable {
    func objectNear(object: Self.Generator.Element, indexModifier: Int) -> Self.Generator.Element? {
        if let index = self.indexOf(object) {
            let newIndex = index.advancedBy(indexModifier) // this doesn't work
            //let newIndex = index.advancedBy(1) // but this this works
            if self.indices.contains(newIndex) {
                return self[newIndex]
            }
        }
        return nil
    }
}

(If there is a more Swifty approach, I would be happy to hear this, but I would like to understand it anyway.)

+4
source share
1 answer

CollectionType has a method

public func indexOf(element: Self.Generator.Element) -> Self.Index?

and corresponds

public protocol Indexable {
    typealias Index : ForwardIndexType
    // ...
}

Finally ForwardIndexTypehas a method

public func advancedBy(n: Self.Distance) -> Self

Therefore, the correct type is Index.Distance:

func objectNear(object: Self.Generator.Element, indexModifier: Index.Distance) -> Self.Generator.Element? { ... }

, endIndex , :

let c = "abc".characters
print(c.objectNear("b", indexModifier: 1)) // Optional("c")
print(c.objectNear("b", indexModifier: 2)) // nil
print(c.objectNear("b", indexModifier: 3)) // fatal error: can not increment endIndex

:

func objectNear(object: Generator.Element, indexModifier: Index.Distance) -> Generator.Element? {
    if let index = indexOf(object) {
        if indexModifier > 0 && index.distanceTo(endIndex) <= indexModifier {
            return nil
        }
        if indexModifier < 0 && startIndex.distanceTo(index) < -indexModifier {
            return nil
        }
        return self[index.advancedBy(indexModifier)]
    }
    return nil
}

, , Int (, Array),

extension CollectionType where Generator.Element : Equatable, Index == Int {

    func objectNear(object: Generator.Element, indexModifier: Int) -> Generator.Element? {
        if let index = self.indexOf(object) {
            let newIndex = index + indexModifier
            if indices.contains(newIndex) {
                return self[newIndex]
            }
        }
        return nil
    }
}
+4

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


All Articles