5

Adding this line of code causes my compile time to go from 10 seconds to 3 minutes.

var resultsArray = hashTagParticipantCodes + prefixParticipantCodes + asterixParticipantCodes + attPrefixParticipantCodes + attURLParticipantCodes

Changing it to this brings the compile time back down to normal.

var resultsArray = hashTagParticipantCodes
resultsArray += prefixParticipantCodes
resultsArray += asterixParticipantCodes
resultsArray += attPrefixParticipantCodes
resultsArray += attURLParticipantCodes

Why does the first line cause my compile time to slow down so drastically and is there a more elegant way to merge these Arrays than the 5 line solution I've posted?

Declan McKenna
  • 4,321
  • 6
  • 54
  • 72
  • 2
    Strongly related: http://stackoverflow.com/questions/29707622/bizarre-swift-compiler-error-expression-too-complex-on-a-string-concatenation. – Martin R Sep 14 '16 at 12:55
  • @MartinR Thanks that certainly explains why this happens, I'll rephrase this so the emphasis is on an elegant solution that doesn't cause a slow down. – Declan McKenna Sep 14 '16 at 13:19
  • 1
    Are all operands arrays? I don't think there is a general recipe. Sometimes an explicit type annotation on the result helps: `var resultsArray: [YourType] = a + b + c + d + e`. See also http://stackoverflow.com/questions/39455123/is-force-unwrapping-a-variable-bad/39455186#comment66231724_39455186 and the following comments which is about the same issue. – Martin R Sep 14 '16 at 13:49
  • What is ArrayLists? A self-contained example would be useful. – Martin R Sep 15 '16 at 09:37
  • @MartinR Ignore my ArrayList comment, they are Arrays. Unfortunately explicit type annotation does not speed things up. – Declan McKenna Sep 15 '16 at 11:24
  • The first one uses the `+` which is heavily ordered. The 2nd one uses `append` which does have to do all the excessive checking due to overloading. For more information just see Martin's link in the comment above – mfaani Mar 12 '17 at 15:46

1 Answers1

11

It's always +. Every time people complain about explosive compile times, I ask "do you have chained +?" And it's always yes. It's because + is so heavily overloaded. That said, I think this is dramatically better in Xcode 8, at least in my quick experiment.

You can dramatically speed this up without requiring a var by joining the arrays rather than adding them:

let resultsArray = [hashTagParticipantCodes,
                    prefixParticipantCodes,
                    asterixParticipantCodes, 
                    attPrefixParticipantCodes,
                    attURLParticipantCodes]
                   .joinWithSeparator([]).map{$0}

The .map{$0} at the end is to force it back into an Array (if you need that, otherwise you can just use the lazy FlattenCollection). You can also do it this way:

let resultsArray = Array(
                   [hashTagParticipantCodes,
                    prefixParticipantCodes,
                    asterixParticipantCodes, 
                    attPrefixParticipantCodes,
                    attURLParticipantCodes]
                   .joinWithSeparator([]))

But check Xcode 8; I believe this is at least partially fixed (but using .joined() is still much faster, even in Swift 3).

Rob Napier
  • 286,113
  • 34
  • 456
  • 610