0

I am working to make this code works for optional array, but Xcode complain about:

Cannot assign value of type '[Wrapped.Element]' to type 'Wrapped'

Not sure why should be an error?

extension Optional where Wrapped: RangeReplaceableCollection, Wrapped.Element: Equatable {

    mutating func customAppend(_ value: Wrapped.Element) {
        if (self != nil) {
            self?.append(value)
        }
        else {
            self = [value] // Cannot assign value of type '[Wrapped.Element]' to type 'Wrapped'
        }
    }
    
}
2
  • 1
    The solution is pretty similar to that answer to your question stackoverflow.com/a/73179138/2303865 Commented Aug 3, 2022 at 2:03
  • 1
    Note that the Wrapped.Element's constraint to Equatable there is pointless. Commented Aug 3, 2022 at 3:07

2 Answers 2

1

This will compile:

extension Optional where Wrapped: RangeReplaceableCollection, Wrapped.Element: Equatable {
    mutating func customAppend(_ value: Wrapped.Element) {
        if (self != nil) {
            self?.append(value)
        }
        else {
            self = .init([value]) // <--- RangeReplaceableCollection.init(_ elements:)
        }
    }
    
}

This works because RangeReplaceableCollection declares this init:

init<S>(_ elements: S) where S : Sequence, Self.Element == S.Element

So that init is available to any conforming type, and gives the appropriate concrete type.

On the other hand, trying to do self = [value] doesn't work, because that's trying to set self to an Array. But since the extension is on RangeReplaceableCollection, you can't set self to an Array, because that's not its type.

Sign up to request clarification or add additional context in comments.

5 Comments

Why not simply init if nil and then just append? if self == nil { self = .init() } self?.append(value)
@LeoDabus Sure! That would be equivalent and maybe clearer.
Your answer is not enough as a correct answer, there is no initialization for RangeReplaceableCollection as you commented like "RangeReplaceableCollection.init(_ elements:)" or in explaining, Also there is no need to use Equatable protocol as Leo said! Your answer does some issues, also you just used .init() which that is not enough, you could say Wrapped.init([value]) or Wrapped([value])
RangeReplaceableCollection does declare that init, here's documentation: developer.apple.com/documentation/swift/…
Additionally, .init([value]) and Wrapped([value]) are equivalent here. This is because of type inference: the compiler knows that self is of type Wrapped, so it infers that .init([value]) actually means Wrapped.init([value])
0

Here is the correct and simplified answer:

extension Optional where Wrapped: RangeReplaceableCollection {

    mutating func customAppend(_ value: Wrapped.Element) {
        if (self != nil) {
            self?.append(value)
        }
        else {
            self = Wrapped([value])
        }
    }
    
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.