Safely invoking removeAtIndex

Michelle Elliot saw my post on safe indexing and asks: Is there a similar easy syntax for safely invoking removeAtIndex(index: Int) -> Element?

Here’s what I came up with. You need to call it with safe and it returns an optional. Improvements, issues, and suggestions are as always welcome.

public extension RangeReplaceableCollectionType where Index: Comparable {
    public subscript (safe index: Index) -> Generator.Element? {
        get {
            guard indices ~= index else { return nil }
            return self[index]
        }
        set {
            guard indices ~= index else { return }
            if let newValue = newValue {
                self.removeAtIndex(index)
                self.insert(newValue, atIndex: index)
            }
        }
    }
    
    public mutating func removeAtIndex(safe index: Self.Index) -> Self.Generator.Element? {
        guard indices ~= index else { return nil}
        return self.removeAtIndex(index)
    }
}

2 Comments

  • What is your take on using the Swift 2 “guard case” syntax vs using the “~=” expression pattern?

    guard case indices = index else { return nil }

    vs.

    guard indices ~= index else { return nil }

    • I don’t think I’ve seen a use of guard case like that. The only guard case I’ve used looks like:

      enum Test {case a(Int), b(String)}
      
      let x = Test.a(2)
      let y = Test.b("Hello")
      
      guard case Test.a(let value) = x else {
          fatalError("shouldn't fire")
      }
      
      guard case Test.b(let value) = x else {
          fatalError("will fire")
      }

      Update

      Wow!

      let foo = "abcdef".characters
      let bar = "abcdefghij".characters
      guard case foo.indices = foo.startIndex else {fatalError("won't fail")}
      guard case foo.indices = bar.endIndex.predecessor() else {fatalError("fails")}