ambiguous reference to member ‘joined()’

You can readily tell that Swift was created by a C++ fanatic, by its fucking obtuse error messages.

⤹ Me             Swift compiler ⤵︎
"What do you want" scene from The Notebook

In today’s episode of “what the fuck do you want, compiler?”, we tackle:

foo.swift:186:39: error: ambiguous reference to member 'joined()'
       log.debug("\(thingies.joined(separator: ", "))")
Swift.BidirectionalCollection:27:17: note: found this candidate
 public func joined() -> FlattenBidirectionalCollection<Self>
Swift.Sequence:27:17: note: found this candidate
 public func joined() -> FlattenSequence<Self>
Swift.Sequence:18:17: note: found this candidate
 public func joined<Separator : Sequence where Separator.Iterator.Element == Iterator.Element.Iterator.Element>(separator: Separator) -> JoinedSequence<Self>
Swift.Sequence:16:17: note: found this candidate
 public func joined(separator: String = default) -> String
Swift.Collection:27:17: note: found this candidate
 public func joined() -> FlattenCollection<Self>

For context, ‘thingies’ is an array of a custom type.

What the compiler wishes it could say, if it weren’t incompetent, is that every one of Array’s ‘joined’ implementations are conditional.  The one that I want is is the second last one, but it is only defined for Array<String> specifically.  No other Array types.

Similarly every other one is conditional on the Element type within the Array being a specific type or protocol, none of which happen to apply to the types I’m using in my Array.

Now, my intuition is that since my type is CustomDebugStringConvertible, that Swift would know then how to convert my type to a String and then go from there.  For better or worse, however, it does not.  Instead you have to do it manually, e.g.:

log.debug("\({ String(describing: $0) }).joined(separator: ", "))")

And you can probably tell from that alone that I’m very used to Objective-C, where it’s very easy to write what you intend and get the results you intend.

Leave a Reply