Implementing += for optional arrays


(Rick M) #1

When working with URLComponents query items, it would be nice to write code like this:

var oqi: [URLQueryItem]? = [..., ..., ...]

var comps = URLComponents(…)
comps.queryItems += oqi

The problem is that queryItems is [URLQueryItem]?, and so I can't just append. I'd like to write a version of += that:

• Takes an LHS of [URLQueryItems]?, RHS of [things possibly derived from URLQueryItem]?
• if LHS != nil, make an array of LHS, and optionally append RHS, and return that
• if LHS == nil && RHS != nil, return RHS
• If both are nil, return nil

I'd like to do this in a generic way that works for any type on the left and possibly-dervied types on the right.

···

--
Rick Mann
rmann@latencyzero.com


(Ben Cohen) #2

Hi Rick,

I think you’re looking for something like this? Assuming when you say “return” in your bullet spec you mean assign-in-place since we’re talking about +=

func +=<T>(lhs: inout [T]?, rhs: [T]?) {
    switch (lhs,rhs) {
    case (_,nil): return // no-op whether lhs is nil or not when rhs is
    case (nil,_?): lhs = rhs // lhs of nil gets replaced
    case (_?,let rhs?): lhs!.append(contentsOf: rhs) // neither nil: append in-place
    }
}

(you could make rhs generic over sequences too but then you don’t get automatic handling of subclasses of T on the rhs)

But it’s probably not a good idea to overload += like this since the extra handling of nils, especially on the lhs, is a bit out of the expected behavior for += and could backfire if you accidentally used it somewhere you didn’t expect. So maybe make it a method with a new name, like:

extension Optional where Wrapped: RangeReplaceableCollection {
    mutating func maybeAppend(others: [Wrapped.Iterator.Element]?) {
        switch (self,others) {
        case (_,nil): return
        case (nil,let x?): self = Wrapped(x)
        case (_?,let x?): self!.append(contentsOf: x)
        }
    }
}

···

On Oct 20, 2016, at 5:17 PM, Rick Mann via swift-users <swift-users@swift.org> wrote:

When working with URLComponents query items, it would be nice to write code like this:

var oqi: [URLQueryItem]? = [..., ..., ...]

var comps = URLComponents(…)
comps.queryItems += oqi

The problem is that queryItems is [URLQueryItem]?, and so I can't just append. I'd like to write a version of += that:

• Takes an LHS of [URLQueryItems]?, RHS of [things possibly derived from URLQueryItem]?
• if LHS != nil, make an array of LHS, and optionally append RHS, and return that
• if LHS == nil && RHS != nil, return RHS
• If both are nil, return nil

I'd like to do this in a generic way that works for any type on the left and possibly-dervied types on the right.

--
Rick Mann
rmann@latencyzero.com

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users