Stupid Swift error message #a bajillion and one

Input code:

let componentsOfPotentialInterest = [Calendar.Component: ((Int) -> String)](
 .day: { String($0 + 1) },
)

Push button.  Expect results (or at least bacon).  Get:

Foo.swift:76:21: error: expected ',' separator
 .day: { String($0 + 1) },
     ^
     ,
Foo.swift:76:21: error: expected expression in list of expressions
 .day: { String($0 + 1) },
     ^
Foo.swift:76:21: error: expected ',' separator
 .day: { String($0 + 1) },
     ^
     ,

Believe it or not, Swift, blindly repeating your obtuse error messages does not help.

What it’s trying but as usual failing miserably to tell me is that Dictionary doesn’t have an initialiser that takes key: value pairs (my mistake for writing straight-forward, Python-like code).  You have to use the dictionary literal syntax instead:

let componentsOfPotentialInterest: [Calendar.Component: ((Int) -> String)] = [
 .day: { String($0 + 1) },
]

Now it merely complains about the expression being too complex for it’s pathetic little brain, rather than having no fucking clue what you’re doing to begin with.  Pick your utterly useless poison, I suppose.

Big words hurt Swift’s tiny little brain

Foo.swift:75:49: error: expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions
 let componentsOfPotentialInterest = [(Calendar.Component, ((Int) -> String))](
                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The fuck?

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("\(thingies.map({ 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.