Welcoming our new Swift 2.2 Overlords

All hail Xcode Beta 7.3 and Swift 2.2. It’s here and there’s so much in there. Here’s a first take at some of the major 2.2 features.

Like my posts? Consider buying a book or two. Thanks!

Parameters don’t need backticks

Doug Gregor proposed SE-0001, which allows using (most) keywords as argument labels. As a consequence, argument labels and parameter names can now be any keyword except `var`, `let`, or `inout`.

Screen Shot 2016-01-26 at 11.49.12 AM

The compiler now automagically warns you about, for example, `defer` in this screenshot. It provides a built-in fixit to change the external label to defer.

Note that Xcode makes no exceptions for , no matter whether you’re a nudist, letting agent, or pirate. “Vaaaaaarrrr, me hearties!”

myFunction(inout: NavelType, let: Rental, and var: PirateCall)

++ and — are deprecated

Chris Lattner has gone to war against ++ and –, via SE-0004. He writes, “Code that actually uses the result value of these operators is often confusing and subtle to a reader/maintainer of code. They encourage “overly tricky” code which may be cute, but difficult to understand….While Swift has well defined order of evaluation, any code that depended on it (like foo(++a, a++)) would be undesirable even if it was well-defined…these fail the metric of “if we didn’t already have these, would we add them to Swift 3?””

The release notes say, “As a replacement, use x += 1 on integer or floating point types, and x = x.successor() on Index types.” The biggest choke point for this is usually in loops and at return points. If you have a postfix increment or decrement that looks like this:

return foo++

refactor with defer

{
    defer {foo += 1}
    ...
    return foo
}

For prefix increment, like return --foo, just prepend the return:

{
    ...
    foo -= 1; return foo
}

You obviously don’t have to put both items on a single line the way I did here.

Deprecated C-style for loops

Never for;;get. Never surrender. Start refactoring your loops. They are deprecated in 2.2 and scheduled for removal in Swift 3.0.

Many loops can simply be expressed as for-in. (The Swift team is working on enhancing performance for these.) Others with complex conditions and side effects will need more tender care. Don’t forget that Swift supports labeled breaks and continues:

Swift Configurations

Important, especially for larger groups, Swift 2.2 introduces the new build configuration #if swift(>=x.y) via SE-0020. This enables you to provide language-specific blocks so your code breaks less. Unfortunately, it’s not exactly working just yet:

Screen Shot 2016-01-26 at 12.11.30 PM

Reimagined Currying

As the screenshot above shows, Swift 3 will also remove currying. I dived into this issue in my Bidding Farewell to Currying post. As you see at the bottom of the post, moving to a non-curried version is actually no big deal, and retains all the benefits of the special-form code. This update is courtesy of Joe Groff’s SE-0002.

Failable and Throwing Init Escape Clause

Designated initializers can now exit before initializing stored properties and/or calling super-init, a welcome relief for those who didn’t know why, when an initialization was going to fail, they still had to do all the “paperwork” of setting up an instance that would never be used.

Tuple Comparisons

Thank Lily Ballard for this great tweak courtesy of SE-0015. You can now compare tuples of Equatable and Comparable elements, up to 6 members at a time.

Screen Shot 2016-01-26 at 12.22.49 PM

Enhanced Document Markup

Beta 2 introduces three new structured markup keywords (I’ll get these into a Swift Documentation Markup update for iBooks within the next day or so.) Welcome - keyword:, - recommended:, and -recommendedover:.

  • Keywords specify searchable concepts that may not otherwise be present in the code or your overall description. It’s a great way for relating semantic concepts to your implementations.
  • Recommendations provide forward referrals (other implementations are preferred over this one) and backward referrals (prefer this implementation to another declaration).

This is great stuff and I look forward to seeing the markup tags grow to match the current sets of semantic decorations currently used in other systems like Doxygen, JavaDoc, ReStructured Text, etc.

Misc:

  • Anonymous structs sourced from C are now imported as nested struct types in Swift.
  • You can now use @objc(SomeName) attributes on enums and enum cases, enabling you to rename the Objective-C declarations that are generated.
  • All slice types now have removeFirst and removeLast, and element indices are all preserved in the slice.
  • Operators that start with dots can contain secondary dots but non-dot-started operators cannot. Apple writes, “The operator identifier lexer grammar has been revised to simplify the rules for operators that start with a dot (“.”). The new rule is that an operator that starts with a dot may contain other dots in it, but operators that start with some other character may not contain dots…This eliminates a special case for the ..< operator, folding it into a simple and consistent rule.”
  • Drop your anyGenerator() calls and use AnyGenerator initializers instead. I have a fair number of these to update. Deprecated in 2.2, gone in Swift 3.

18 Comments

  • for;; removal is just insane, for example: stride(to: … & stride(through: aren’t as intuitive as < or <=, but the worst part is how bacly these generator types perform.
    I have no problem with streamlining Swift, but the alternatices shouldn't less intuitive syntax or suck with performance.

  • So now one can simply return nil in a failable init at any point? Nice.
    Getting rid of old school for loops might feel weird at first. What about float or reversed loop counters?

    • use stride for floating point and reverse. The latter takes a negative “by” argument.

      • Never heard of it and the first Google result brings me back to your blog. Thank you.

  • A lot of useless changes. What about to make math operations to just work between any type?

    • Here here!

    • https://github.com/apple/swift-evolution

      Submit a pull request if you want it. Though that specific thing would be shot down fast, because it’s exactly counter to specific goals for Swift. It’s 100% intentional that Swift does not do implicit type conversion.

      • Yes, we all know it’s a specific intention that Swift will not do implicit type conversion.

        It’s a MASSIVE MISTAKE.

        I have been building software in swift that uses unsigned values of various types, most of which could have benefitted from implicit type conversion big time. What has happened because Swift will not do implicit conversion is:

        1) A big temptation to use data types that do not reflect the data. Swift is encouraging me to use the wrong datatype to avoid me filling my code with explicit type conversions, making my code far less readable. I am processing buffers with fixed file formats and converting to graphical output. The lazy approach to this is just to use CGFloat all over the place as my preferred datatype, rather than unsigned ints.

        2)Worse still, I have a compiler (the worst compiler I have ever used, with the most obtuse errors) that points out all of the conversions required, encouraging me to mindlessly do explicit conversions and turn my elegant code into a mess.

        I completely understand that Swift wants me to choose the right datatypes and trap errors at compile time and not run time. I do however feel it’s more a case of the “emperor’s new clothes” and because the guys in the compiler ivory tower says it’s good for us, it’s not. They encourage people to choose the wrong datatype and mess up their code with explicit conversions. This clever policy has only achieved turning developers into mindlessly doing what a real compiler should do.

        Thousands of programmers are writing rubbish code because of the decision and it slows down development immensely.

        MASSIVE MISTAKE.

        I also greatly dislike the subtext that goes with this decision to not perform implicit conversion, that the developers who still want implicit conversion are somehow inferior or misguided, when all we want is coding simplicity and an encouragement to use the correct datatypes rather than avoid them. Sure we might get a rare run-time error if we screw up. What do you think we might get if we just follow the compiler errors and cast away joyfully?

  • I guess from the ivory tower, ‘for (index, value) in x’ is more elegant than ‘for var i = 0’. In practise I really feel the latter was easier to use and remember, because it is the same construct in several languages. Also the latter is more flexible, for instance let’s say I want to start iterating in the middle of a collection. ‘for var i = collection.count/2’. So thanks Erica for succeeding in removing for ;; after 30 years of service. 😐 Not a fan

    • I recognize your pain. for var i in collection.count / 2 ..< collection.count will continue to work, although I don't quite know why you want to be mutating i. I also would like to point out that changes to Swift won't affect Objective-C and C.

      Thank you for reading the site. And wishing you the best with your programming efforts.

      • Don’t get me wrong, I love the ‘for-in’ expression, I just felt that the classic for-loop still had its place if one wanted to loop over a subset or do some slightly less trivial looping. For example, when starting with an offset like in _for var i = n; i n_. The new way doesn’t look bad at all, it _is_ more verbose though and also raise some questions for me. For example, is y.enumerate() called each time, or once with the range and bounds check in-memory? is the _where-part_ evaluated for each iteration? The well known, compact and optimised C-way to loop is soon history then and I’m going to miss it in some cases. I also worry when I hear that ‘for-in’ has performance problems. Hopefully this will be fixed before the classic for-loop is gone. That’s all. (Ps. I was lying, I am fan, though not always).

  • Great…and no more increments and decrements, bravo! Where is the freedom of choice?

    • Yes, I agree. A lot of Swift reminds me of the old C minimalist code challenges that delighted language geeks but was poor practice for professional developers. Swift seems to be in the hands of a developer elite that enjoys building a quirky language that is uncomfortable for people transitioning from other languages. It is very easy to write obscure code in Swift. It is actively encouraged by the compiler team. I’d rather have a simpler, clear language than one that revels in clever syntax games.

  • I don’t see how ++ and — are confusing. But, I’ve been a developer since 1984. If we could learn it then, how confusing could it possibly be now? A little shorthand never hurt anyone.

    • If you read through the proposal justification, it’s isn’t just about confusion. Lattner writes:

      1. These operators increase the burden to learn Swift as a first programming language – or any other case where you don’t already know these operators from a different language.
      2. Their expressive advantage is minimal – x++ is not much shorter than x += 1.
      3. Swift already deviates from C in that the =, += and other assignment-like operations returns Void (for a number of reasons). These operators are inconsistent with that model.
      4. Swift has powerful features that eliminate many of the common reasons you’d use ++i in a C-style for loop in other languages, so these are relatively infrequently used in well-written Swift code. These features include the for-in loop, ranges, enumerate, map, etc.
      5. Code that actually uses the result value of these operators is often confusing and subtle to a reader/maintainer of code. They encourage “overly tricky” code which may be cute, but difficult to understand.
      6. While Swift has well defined order of evaluation, any code that depended on it (like foo(++a, a++)) would be undesirable even if it was well-defined.
      7. These operators are applicable to relatively few types: integer and floating point scalars, and iterator-like concepts. They do not apply to complex numbers, matrices, etc.

      Finally, these fail the metric of “if we didn’t already have these, would we add them to Swift 3?”

    • I just noticed this.. Paul’s comment “++ is elegant” is right. Oh GOD! Yeah, sure, “++” can be annoying hard to read/easy-to-make-a-mistake if you use it in a “obfuscated-code-contest-lite” loop like “for (int i=0;;i++<5)" (off the top of my head C++). But that really shouldn't be done anyway.

      But what if I just want to add one to something?! Do they really want to force me to write "x = x+1" or "x += 1"? The first is overly verbose, and (I think arguably) LESS readable. With "x++" you simply see the "++" and understanding the meaning "increment-by-one".

      In the "x += 1" case, you first have to see the "+=" and understand "add". Then your brain asks "add what?" Then you read the "1" and understand "adding-amount-direct-object-is-one". Then you finally put it together. As for whether that really adds a "cognitive burden"? No idea. Still, I think the single-understanding-step “increment-by-one”> is better.

      The second form (“x+=1”) is better – it’s only one extra character to type.

      Could you write some kind of “class-extension” (I don’t know much about Swift, so I don’t know if you can extend base types in some way), so you could write “i.++()” That’s looks even MORE horrible, as it might imply there should be a parameter, which doesn’t make sense in a simple “increment-by-one” thought-statement.

      Yeah, I know, back 25 years ago when I wrote Hypertalk, I write “add 1 to i” all the time. But then I learned C++ and I like that little bit of compactness (even though I did unreasonably balk at other things that are less verbose in C than Pascal).

      Well, actually I wrote “repeat with i = 1 to 10”. Does THAT work in Swift?

      I wish they would simply bring Hypercard back and use that as an “Apple-getting-into-the-programming-pedagogy-market” thing like they SHOULD have done work 25 years ago. (Well, more than they did – they create Hypercard, but didn’t do the “school-programming-advocacy” work) Bring it back (version 3.0) with NO changes. THEN and only then start figuring out how to make the syntactic sugar needed for things like real objects, variable-pointer-references, closures, etc.

      Make it into a sort of “hypercard-plus-objective-c” thing (!). In some ways, this is Swift (I think – as I said, I don’t really know the language). In others.. no. Applescript is the same way.

      And (even though this is the irrational-childhood-programming-love-of-syntactic-sugar-thing here), *don’t* change anything about the syntax. Don’t change “put 5 into x” into something like “copy 5 to x” like Applescript does. I don’t get *why* you could “copy” a *constant* INTO a “box” (variable). You copy an instance of one “thing” that exists in one “box” into *another* “box”. Things that don’t exist previous to the “action verb” (meaning script statement) *can’t* be “copied” because they don’t exist beforehand in the “thought space of the program”. They are “put”.

      Actually, I suppose the “syntax-thinking” should depend on whether the original contain ceases to exist or not. “Copy” should specifically means the original container DOES NOT cease to exist. I’m not sure where “put” versus “move” should be on that count. Constants *cannot* cease to exist, so maybe it should be “copy”. Hypertalk didn’t any concept of “undefined variable”, so that question couldn’t come up when designing the syntactic sugar.

      Maybe Apple should just buy Runtime Revolution, which would be the same thing.

      Jim

  • Quite honestly, it astounds me that anyone thinks that removing these concise operators are a force for good.

    All of the suggestions for refactoring “return foo++” are clunky and in some cases VERY counterproductive.

    For example, I look at “return foo++” and I know exactly what is going on.

    I look at

    “{
    defer {foo += 1}

    return foo
    }”

    and I can see that my intention ( to increment foo on exit ) is now entirely divorced from the return itself. There may be thirty lines of code between defer and return. Anyone looking at the code can see the return, but needs to be very careful not to miss the intended action before returning.

    foo++ is elegant. I can’t follow the reasoning that it isn’t.

    Would I add the ++ and similar, family of operators to any language I designed? You bet I would.

    Swift is becoming more and more like the emperors new clothes. It claims to make programming simpler, but increasingly it’s becoming bloated and less accessible.

    My own code is much harder to read because of the intransigence of the developers forcing me to cast with CGFloat, turning me into a human compiler.
    I have a choice to use appropriate variable types in my code, UInt, Int8, etc. and no end of CGFloat, of just make my variables all CGFloats to reduce the casting.

    This is very bad.

    • Oh, and the term overlord may be appropriate, but also quite insulting. We have people dictating to us how we develop software and removing choice.