Archive for May, 2016

Swift 3.0 Preview 1 Release Branch

Screen Shot 2016-05-31 at 4.53.05 PM

Hop over to swift.org to download the first Swift 3.0 PR 1 installer.  Double-click to install, authenticate as admin. Once you do, the toolchain will appear in the Xcode > Toolchains submenu.

Screen Shot 2016-05-31 at 4.54.39 PM

When you select a new toolchain, Xcode needs to quit and relaunch. It will ask you to confirm that’s what you want to do. Give it a few seconds to catch up with itself.

3.0 PR 1 is not compatible with playgrounds. The easiest way to play around with code is to create a Cocoa command-line app (or, if you really need to, use a single view UIKit app, but it’s a lot more complicated) to try out the new syntax, test libraries, and get a feel for what’s new and changed.

Screen Shot 2016-05-31 at 4.56.19 PM

Now that the toolchain is readily available, I’ll be posting highlights of new features when I get some time.

Swift rewrite challenge

In searching around this morning for some examples of complicated if-then-else-else-else statements on gist (if you have any, please point me to them!), I stumbled across this function for scaling and cropping an image.

I immediately decided to re-write the function in my more personal style, to see what kind of changes I’d introduce and whether any of them could be generalized and discussed as  potential book fodder / post fodder.

Before looking at my version, which is here, you may want to whip up your own take on things and then return to see why I made some of the decisions to introduce changes in my take on it.

My Changes

If you do the math, my version takes about the same number of lines as the original, both are about 38-43 lines of code. Both use Swift 2 code and not Swift 3 code. My code uses more comments, fewer vars, more lets, more conjoined code, and more multi-line calls.

While the original performs a fill-image operation, mine does both fit and fill, using defaulted arguments, which is one of the reasons my function signature occupies 5 lines compared to the original 1-line signature. I find myself more and more breaking signatures down to multiple lines to allow better labeling, defaulting, and documentation.

I’m less worried these days about taking up vertical space as I find that stacked parameter lists are easier to read and understand. Each parameter line may contain an external label, an internal label, a type, and possibly a defaulted value. Swift’s move towards complex parameters deserves the presentation that best exposes these items to their full expression.

Next, I converted the initial if-check to a guard statement. When a function’s code is meant to test initial conditions and immediately leave scope if those conditions are met, it seems to me a guard statement better represents that entry point than “if”.

In calculating the scale factor, I perform a tuple assignment. These factors are semantically parallel, so their assignment is joined and parallelized as well. It’s a fairly Swift-specific approach, and one that should be used sparingly but this fits my parallelism criteria, and I do the same just below when calculating the scaled width and height.

I follow this with a pair of ternary tests, first for choosing whether to use fit or fill, and then choosing the scale factor that applies the fit or fill set by the fitImage Boolean parameter. I think it’s pretty straight forward. A fit operation constrains itself to the smaller of the two scales and a fill to the larger.

In creating the drawing destination, I decided to break out my CGPoint construction to three lines. Again I felt this read better and was easier to follow than placing both the x and y parameters on a single line, which grew quite long. The top-down alignment draws attention to the parallels between x and y and width and height used in the two parameters.

I took some liberties in the UIGraphics drawing section, deciding to use a do clause for the actual drawing. In Objective-C, I often use scoping to distinguish the drawing operations from the bracketing begin and end calls. Because of scoping, I had to pull the scaledImage constant declaration out of the do clause but since Swift now lets me defer the assignment to the constant, this worked out pretty nicely.

In the drawing block, I decided to place the background fill on a single line. I initially had this on two lines, but felt it was drawing too much attention away from the actual operation (drawing the scaled image) so merged the two calls using a semicolon.

In contrast, I broke out the scaled image drawing over three lines, to emphasize the use of the calculated destination bounds. I wanted to expand the details of this operation while minimizing the background fill.

Testing

There’s some sample tests at the bottom of my version if you want to throw this into a playground and test with real data. The placeholder generator website (http://placehold.it) creates simple block images along whatever dimensions you request.

I’m interested in seeing the kinds of rewrites you came up with and what kind of Swift rules they incorporate. Disagree or agree with my edits? Please let me know. My style choices are still evolving.

Cenozoic Park: Swift Evolution

Accepted

SE-0093: Adding a public base property to slices. “Slice types provided by the standard library should allow public readonly access to their base collections to make efficient implementations of protocol requirements possible in conforming types.” Team writes:

  • There was little feedback from the community other than to get clarification.
  • The core team recognizes the proposal as exposing an important basis operation of slice types.

SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib is accepted (with a tiny revision). “This proposal introduces sequence(first:next:) and sequence(state:next:), a pair of global functions that return (potentially-infinite) sequences of lazy applications of a closure to an initial value or a mutable state.” Team feedback:

  • Feedback from the community & core team is positive.
  • Core team discussed whether it made sense to add just the first form, or whether it made sense to add both. They agree that although the form using an explicit state is much more infrequently used, when it is necessary, it is extremely helpful to have. It is also useful to consider both as a pair.
  • On naming, the core team agrees with the community that “sequence(first:next:)” is a better name than “sequence(initial:next:)”. “sequence(state:next:)” is approved as-is.

Deferred / Returned for Revisions

SE-0083: Remove bridging conversion behavior from dynamic casts is deferred for re-evaluation later in Swift 3. “Dynamic casts using as?as!, and is are currently able to dynamically perform Cocoa bridging conversions, such as from String to NSString or from an ErrorProtocol-conforming type to NSError. This functionality should be removed to make dynamic cast behavior simpler, more efficient, and easier to understand. To replace this functionality, initializers should be added to bridged types, providing an interface for these conversions that’s more consistent with the conventions of the standard library.” Team writes:

The core team and much of the community would like to get the predictability wins of this proposal. However, recent experience with the fallout of “SE-0072: Fully eliminate implicit bridging conversions from Swift” has raised some concerns that it may have overly harmed Objective-C APIs designed around the “id” type. Joe Groff will be investigating a few ideas that may help make SE-0072 work better in practice, and until they are explored and understood, the core team prefers to defer discussion on SE-0083.

Once we have clarity on the fate of SE-0072 (in the next 3-6 weeks), we can discuss SE-0083 again. Thank you to Joe Groff for this proposal, and also for helping to sort out the issues related to SE-0072.

SE-0089: Renaming String.init<T>(_: T) is returned for revisions. “Swift’s String type ships with a large number of initializers that take one unlabeled argument. One of these initializers, defined as init<T>(_: T), is used to create a string containing the textual representation of an object. It is very easy to write code which accidentally invokes this initializer by accident, when one of the other synonymous initializers was desired. Such code will compile without warnings and can be very difficult to detect.” The core team would love to see the revised proposal make it into Swift 3. The team writes:

The community and core team both want to remove this “footgun” from the standard library, where someone could write “String(x)” with the intention of getting a value-preserving conversion to String, but may instead get a potentially lossy and potentially expensive reflection-based conversion to a String.  After extensive discussion, the core team recommends that the community consider a somewhat more elaborate design:

  • Rename the existing reflection-based “String.init<T>(_: T)” initializer to “String.init<T>(describing: T)” as recommend by the community.  This initializer would rarely be invoked in user code directly.
  • Introduce a new protocol (for sake of discussion, call it “ValuePreservingStringConvertible“) that refines CustomStringConvertible but that adds no new requirements.  Conformance to this protocol indicates that the “description” requirement produces a value-preserving representation in String form.
  • Introduce a new unlabeled initializer on String: “init<T: ValuePreservingStringConvertible>(_ v: T) { return v.description }“.  This permits the “String(x)” syntax to be used on all values of types that can be converted to string in a value-preserving way.
  • Audit important standard library types (e.g. the integer and floating point types), and make them explicitly conform to ValuePreservingStringConvertible with an explicitly implemented “description” property.
  • As a performance optimization, change the implementation of the string literal interpolation syntax to prefer the unlabeled initializer when interpolating a type that is ValuePreservingStringConvertible or that has otherwise has an unlabeled String initializer, but use the “String.init<T>(describing: T)” initializer if not.

The expected advantages of this design are:

  • Swift encourages the T(x) syntax for value preserving conversions, and this design ensures that String(x) continues to work for the value preserving cases.
  • This ensures that the String(x) syntax does not accidentally fall off a performance cliff by using the extremely-dynamic reflection mechanism unintentionally.
  • The preferred “I don’t care how you do it, just convert this value to a string somehow” syntax remains string interpolation syntax.  This syntax is efficient in the cases where the String(x) syntax is allowed, but fully general to the other cases where custom convert-to-string code has not been provided.

Some remaining open questions:

  • Exactly what types should conform to ValuePreservingStringConvertible.  It seems clear that integer, floating point types, and Character can and should conform.  What other types should?
  • Do we need the ValuePreservingStringConvertible at all, or is the existing CustomStringConvertible enough?  We already have a few protocols for handling string convertibility, it would be great to avoid adding another one.

SE-0090: Remove .self and freely allow type references in expressions has been deferred from Swift 3. “Swift’s grammar currently requires that type references only appear as part of a constructor call T(x) or member access T.x. To get the metatype object for T, one must refer to the special member T.self. I propose allowing type references to appear freely in expressions and removing the .self member from the language.” Team feedback:

The community and core team all want this proposal (or something like it) to succeed, but the core team identified several serious implementation concerns with the proposal:

  • Disambiguating type vs expression cannot be done in cases where there is no contextual type available or when that type is “Any”.  For example, in the case of “let x = [Int]” it isn’t clear whether this is an array value that contains the metatype for Int, or whether it is a metatype value for the type “[Int]”.  Similar problems exist with tuple literals, including the degenerate case of “let x = ()” which can either be the type of the empty tuple type or an empty tuple value.
  • As written, the proposal has a defaulting rule that fall back to the container literal when a type literal cannot be formed.  The core team prefers that the compiler treat truly ambiguous cases (where a subexpression could be considered to be either a type or a value) to be ambiguous.
  • Resolving ambiguous cases requires some syntax to disambiguate between the cases, which we don’t have.  This syntax should be part of the proposal.
  • Having the constraint solver determine whether a subexpression is in a type or expression context is conceptually beautiful, but it introduces significant complexity into the type checker and puts more pressure onto the constraint solver.  The core team would prefer to see the already planned optimizations and simplifications go into the constraint solver before this happens.  This would allow us to more accurately gauge the cost of this design in practice.
  • The goal of removing the “Int.self” syntax is a great one, but can be done at any point (beyond Swift 3) at little cost: the goal is to obsolete the T.self syntax, not to repurpose it to mean something else.  This means that we can continue to accept it as deprecated syntax for a very long time with little cost to the community.

The core team would definitely like to circle back to this proposal after Swift 3 is out the door, but would recommend that such a proposal be accompanied with a prototype implementation, to validation that the chosen approach can work in practice.

Joe Groff has posted an updated version incorporating feedback.

Rejected

SE-0087: Rename lazy to @lazy is rejected. “Make lazy declaration modifier an attribute by renaming it to @lazy" Team writes:

The community feedback on this proposal was that the most important thing was for the syntax to align with that of the forthcoming property behavior syntax. The core team does not know what that syntax will be, so it prefers to reject this proposal. While it would be great to align “lazy” with behavior syntax, but the cost of it diverging is very low (it is easy and not harmful to accept this as a legacy syntax for a long time if the preferred syntax changes in the future), and it would be worse to switch “lazy” to “@lazy” in Swift 3, only to switch it to something else in a subsequent release.

SE-0084: Allow trailing commas in parameter lists and tuples is rejected. “Swift permits trailing commas after the last element in array or dictionary literal. This proposal extends that to parameters and tuples.” Team writes:

The feedback from the community was quite divided on this topic: many people contributed to the discussion thread with some people agreeing and some disagreeing.

Swift currently accepts a trailing comma in array and dictionary collection literals, for three reasons: evolution of a project often adds and removes elements to the collection over time, these changes do not alter the type of the collection (so those changes are typically spot changes), and the closing sigil of the collection (a right square bracket) is often placed on the line *following* the elements of the collection. Because of these properties, accepting a trailing comma in a collection literal can help reduce spurious diffs when elements are added or removed.

That said, these properties do not translate to other comma separated lists in Swift, such as variable bindings in a var/let declaration, parameter lists or tuples. For parameter lists and tuples (the specific topic of the proposal), the trailing terminator of the list is typically placed on the same line as the other elements. Further, changes to add or remove an element to a parameter list or tuple element list change the type of the tuple or the signature of the call, meaning that there is almost always changes in other parts of the code to allow the change to build. Finally, the core team does not want to encourage or endorse a coding style that puts the terminating right parenthesis on a line following the arguments to that call.

I was rather hoping that the core team might agree that they be allowed just at call-sites, where changes would not propagate to other parts of the code but allow the easy inclusion and exclusion of defaulted arguments.  It wasn’t to be.

Active Reviews

Awaiting Scheduling

Trailing commas, open source, and community participation

The wave of support, kind words, and tweets after the rejection of SE-0084, which introduced support for trailing commas in declarations and at call sites, has been very kind but rather misses the point of open sourcing the Swift language.

While Apple’s Joe Groff provided a strong voice of support for SE-0084, there were few concurring list members willing to speak up for it.

John Siracusa wrote, “Having used, more or less continuously for my 20 years as a professional programmer, both a language that allows trailing commas and one that does not, I come down pretty strongly on the side of allowing trailing commas (for all the reasons already stated in this thread). If it means requiring a newline after the last comma to make some people feel better about it, so be it.”

Brent Royal-Gordon also voted in favor, “I was skeptical of this until a week or two ago, when I had some code where I ended up commenting out certain parameters. Removing the now-trailing commas was an inconvenience. So, +1 from me.”

The remaining community votes were almost entirely negative, with a special award for honesty for Chris Lattner, “I personally find that style repulsive.” In this light, comparisons to Perl and C that show up after the review period has ended don’t add support or change the outcome.

Unless you’re willing to participate in the Swift Evolution process and speak up for or against proposals, the outcomes may not reflect your specific development needs. The best arguments for or against a proposal are real world code, measurements of use in public and private libraries, and pragmatic use-cases that express why a proposal should be adopted or not. Swift language changes should fix real problems and must be demonstrated with real data.

The best evolution reviews include thoughtful analysis of how a change affects existing code bases, improves outcomes, and compares to other programming languages. They should analyze how the proposal fits with the specific feel and direction of the Swift language. A surprising quantity of review feedback ends up as “+1” or “-1”  one-liners, which don’t really help guide the evaluation of a proposal’s merits.

Evolution members are welcome to post their reviews publicly or to directly contact the review manager with private feedback. I have participated privately in a handful of reviews and publicly in others. I’ve abstained from reviewing many proposals (there are now over a hundred of them) when I had no strong feelings or no background to evaluate a topic.

Swift Evolution, as all open source projects, offers an imperfect process:

  • There is far too much on-list traffic to keep up with. It helps if you’re specifically dedicated to documenting the language and its process, which is an extreme outlier case.
  • Participants are self-selected and skew towards people who dedicate time to debating language design; that time must naturally trade off from work, spending time with family, watching TV, or engaging in other lifestyle activities and hobbies.
  • On-list consensus may not match the consensus in the wider developer community and there’s often quite a strong backlash against attempting to measure the temperature of that wider community.
  • If you think “best editor” wars are bad, you haven’t seen the bikeshedding over multi-line string grammar.

To be clear, Swift Evolution is not “design by committee” as some mass wave of crowd consensus. The Swift process was designed from the start to be both opinionated (“Swift is an opinionated language”) and  focused given the circumstances or community involvement. At this point, I can’t remember if Apple wrote this or I did, but “maintaining that coherent vision for something as complicated as a programming language requires both coordination and leadership.”

The ultimate responsibility for adopting changes lies with the Swift core team, which acts as Swift’s internal star chamber. The team establishes the strategic direction of Swift. Core team members initiate, participate in, and manage the public review of proposals and have the authority to accept or reject changes to Swift.

The majority of work and discussion take place on the highly-trafficked Swift Evolution mailing list. This list provides the platform to propose, discuss, and review ideas to improve the Swift language and standard library. There are few participation rules, mostly to do with adhering to a respectful code of conduct.

Using a mailing list establishes a public record of all proposed changes and their ensuing discussions. Participants can explore archives to determine whether a topic has already been discussed and/or voted on, and what the arguments for and against those changes were. The Swift Evolution archives are available at lists.swift.org and news.gmane.org.

Having votes go against your preferences is part of the reality, and there are often some very good underlying reasons why some proposals go the way they do that are obvious on the larger scale than the smaller (to simplify the language, to enhance reliability, to obtain more accuracy, precision, and speed, because of the internal compiler limitations, etc.) The core team feedback at the end of the review period explains why each vote went the way it did.

That said, each proposal needs its champions. The process can be tedious and needs to be driven from a pitch through drafts, from pull request through review. Supporters should be available through the review process to answer questions, update text, offer code.

With Apple standing behind Swift, its impact is both large and loud. If you love coding and language design, there’s rarely an opportunity like this to become part of the process and help influence its outcome.

Ordovician Swift: Evolutionary Advances

Accepted

SE-0088: Modernize libdispatch for Swift 3 naming conventions is accepted with revisions. “libdispatch on Darwin already presents Objective-C compatible types to allow its objects to participate in automatic reference counting. We propose extending this support to present a design that feels “object-oriented” and inline with Swift 3’s API guidelines, all without adding runtime overhead.”

Under the current 2.2 system, dispatch looks like this:

let queue = dispatch_queue_create("com.test.myqueue", nil)
dispatch_async(queue) { 
   print("Hello World") // etc
}

The new system modernizes the calls to look “Swifty”, eliminate snake case, and provide a user experience that better mirrors the readability and flow of modern Swift.

let queue = DispatchQueue(label: "com.test.myqueue")
queue.asynchronously {
    print("Hello World") // etc
}

Team feedback:

The community and core team are both very positive about this massive improvement to the libdispatch APIs.  Much of the discussion has centered around specific details in the proposal – for example the “.asynchronously” method on DispatchQueue.  This great discussion leads to several requested revisions in the proposal:

  • Rename the DispatchQueue.[a]synchronously methods to “.async” and “.sync”, to follow the term of art.
  • Rename DispatchIO setHighWater, setLowWater –> setLimit(highWater:), setLimit(lowWater:)
  • Rename setTargetQueue(queue:) and DispatchSource.setTimer
  • Rename Semaphore, Group and WorkItem: .wait(timeout:) –> wait() and wait(withTimeout:)
  • Expand source handler methods to take the same arguments as async()
  • Expand DispatchQueue.after to take the same arguments as async() in addition to the when: argument

SE-0081: Move where clause to end of declaration is accepted. Team feedback:

The feedback on this proposal was strongly positive from the community and core team.  Some concerns were raised (e.g. about possible interaction with the future “generalized existentials” feature) but further examination turned up that they were at issue regardless of whether this feature is accepted.

The core team agrees that this syntactic structure allows a more natural and beautiful way to structure complex generic constraints, and that “where” clauses should be considered secondary to the primary signature of the declaration (e.g. func, class, etc) in question.

SE-0075: Adding a Build Configuration Import Test is accepted.  Team feedback:

The community and core team are both very positive about adding this functionality.  It is precedented by the __has_include feature in Clang, and may have applicability allowing “conditionally available” features for SwiftPM modules in the future.  The core team spent a significant amount of time discussing the proper naming for this, and came to agree that “canImport” (as proposed) is the best name for this conditional.

Rejected

SE-0041: Updating Protocol Naming Conventions for Conversions is rejected. Team feedback:

The feedback on the proposal was generally positive about the idea of renaming these protocols, but the specific names in the proposal are not well received, and there is no apparent confluence in the community on better names.  The core team prefers discussion to continue — if/when there is a strong proposal for a better naming approach, we can reconsider renaming these.

Active Reviews

Upcoming Reviews

Awaiting Scheduling

If you enjoy these Swift Evolution updates and want to say thank you, consider picking up a book or two. Swift Documentation Markup teaches you how to use Swift’s documentation system to better annotate your code. Playground Secrets and Power Tips unlocks the power of Xcode’s Swift playgrounds. And if you’re looking to pick up solid, day-to-day Swift skills, look no further than the Swift Developer’s Cookbook. (It’s not exactly a cookbook but the name was chosen long before WWDC 2015, so we kind of got stuck with the title.)

Swift: Things I really wanted that won’t make it

Here’s a short list of things that aren’t (or probably aren’t) going to be in Swift 3, that I was hoping to see.

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

Fixed Ranges, Striding, and Range Operators. This splintered down into a series of I believe four separate proposals of which only the first one (improving floating point math) has gotten into review. A lot more work to be done here. Plus extending striding to collections.

Disambiguating SPM Naming Conflicts. My idea would be to come up with a way to allow multiple packages to share the same simple names (like “JSON Parser”) and differentiate them based on their source repo. Swift names should be simple and concise. Namespacing modules (“MySwiftStringUtilityCollection”) is very unSwift so overlap is not just likely, it’s already happening.

The language would adjust to add import as as well, so same-named modules (or modules with difficult names, or submodules) could be pulled in with simpler access from code.

Most of this depends on the overworked and overwhelmed build team, plus it would then require a Swift Evolution proposal for the “import as” component. There are already bug reports of package conflicts in the wild and this would introduce a simple way to add resolution.

Introducing Build Configuration tests for Simulator/Device targets. I gave up on even trying to do #if debug (if one is going to do the configuration tests, there doesn’t seem to be a large enough middle group that wants a preconfigured simple test) but I think #if target(device) (vs simulator/emulator) is doable and useful. Backburnered, along with any platform tests (Windows, Linux, Unix, Apple) until there’s time.

Method Cascades. Dart-like for the win. Postponed until after 3.x at a minimum. It’s language additive, which makes it less critical for 3.

Interpolated String Formatting. Brent Royal Gordon started this off and then it went into limbo. I think it’s important to be able to not just add \(aFloat) into strings but be able to do some kind of inline safe formatting about the number of decimal places, leading zeros, etc.

Core Error. Not hugely popular but not entirely dead, I thought it would be nice to have a built-in basic “default error” to throw that included source site (where the error was thrown) and an optional customizable string and/or dictionary. This wouldn’t replace any other errors but it would provide a convenient error for anyone building scripts and playgrounds (or, let’s be honest, simple apps) where you didn’t want to build something more carefully and extensive with individual error condition cases.

Macros. Didn’t happen. Won’t happen for a while.

Decimal Numbers. Ditto.

Duplicating and modifying immutable structs. Brought up “with” on list, showed an implementation, it got discussed, went nowhere.

Final by default for Swift-sourced classes (would not apply to anything from ObjC), where you enable subclassing rather than disable it. Seemed to split down between Swifties (for it), ObjCHeads (against it).

A Result Type for use in completion blocks, rather than the data, status, error signature we currently have. Big war over Result (specific use case, measurable benefit) and Either (just a thing that could be built and used for this). I prefer Result.

Intrinsic Member Collection for Enumerations. There’s a pull request but that’s about it.

Expanding Cocoa Touch Defaults. The idea was to take a cue from the better-imports from ObjC (SE-0005) and extend the pruning and defaults to other common classes. This isn’t a Swift Evolution process but I have no contact point with whom to take it up with for Foundation and UIKit. (initial unreviewed list), and I’m not yet satisfied with which defaults I actually want to push on.

There’s actually two more items on my list that just might squeak through:

Adding the Unfold Sequence. Lily’s sequence -> UnfoldSequence  was part of SE-0045 and the only part of the proposal not to be accepted. After a spate of bikeshedding, I think the name sequence() was not hated, but it’s unclear whether this needs a new proposal (it’s getting kind of late to the party) or can be shoehorned in. SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib in review to 5/23

Evan Maloney’s end to the Strong Weak DanceI was writing this up, and I checked the pull request and behold, it is now in the proposal queue as SE-0079. Still not sure this will go through but it would make coding a lot better.

Okay, that’s my (partial) list. What’s yours?

If I had my druthers: Swift 2.2, Swift 3.0, ABIs, etc

If I could wave a magic wand, I’d push Swift 3.0 out by a year or even better three years and fix Swift 2 as the standard App Store language (and for Linux, and upcoming Windows) exactly as is, barring a few tweaks and fixes over this time.

[tl;dr summary: Make big breaking changes later and once rather than sooner and multiple times. If a delay allows a single stable language transition, it is to be preferred. Aim for post-3.0 language updates to be additive not transformative.]

Swift 2.2 is a great language. It’s amazing to work in. It offers utility and concepts that Objective-C cannot provide. It pushes iOS and OS X development forward in an important and exciting way, affecting development not just on Apple platforms but wherever Swift touches. From first class structure and enumeration types to protocol oriented programming, Swift 2.2 delivers the goodies.

If you need just one compelling single example, take CGRect: Swift 2.2 lets you expand this essential structure with methods and properties that let you center on a zero origin, or scale and transform, or add math to combine instances. It’s so practically useful that going back to ObjC to work in geometry metaphysically hurts.

Swift 2.2 gets it right in so many ways, that it seems ridiculous to throw it away at the end of the year. A language this good should have a lifetime longer than 8 or 10 months. I’d be really happy if at the WWDC keynote, Tim Cook said, “We got it so right, we’re going to stick with Swift 2, let you build your code for long term use, and make sure the transition to Swift 3 will be perfect.”

The move to Swift 3.0 isn’t just going to be disruptive. It’s going to be traumatic. With its expansive renamification and redesigned core types and APIs, Swift 3 is going to be a tidal wave of retraining and refactoring. And with a list of objectives that didn’t quite make the cut, and a laundry list of of items that should have, Swift 3 just doesn’t have enough time or scope to be perfected.

So why not just push it back?  Let us devs use Swift 2.2, which is terrific, for a few more years and get Swift 3 right the first time?

It’s not as if Swift Evolution needs to be fast paced and hectic. The bikeshedding, the simple natural discussion overhead, the need to foster a courteous open source community means the natural speed of development has taken a huge hit.

These arbitrary “update every year” advances that Apple has bought into are more than a little ridiculous when it comes to firmware and OS updates; for languages it pushes beyond the practical.

Orson Welles promised that Paul Masson would sell no wine before its time. Apple should take a lesson from Welles and ship no language before the follow-up version has properly evolved.

I want to see Apple slow down, take some deep breaths, and seriously consider letting Swift 2.2 come into its own rather than cutting it down after a few months of use.

As it is, I am constantly having to answer “Is it time yet to switch to Swift?” As this breakneck development continues, I’ve been hesitant to recommend jumping aboard the Swift train for simple practical reasons.

I’d be far more confident with my advice if I could see a 2-3 year window with stable code that could benefit from Swift’s modern language features, and a payoff of investment in training and refactoring that won’t have to be re-addressed with each new beta and each new release.

To paraphrase a line from Aesop, slow and steady really does win the language race.

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

Playing with the future

A few test runs for fun.

Proposal SE-0071. “Allow (most) keywords in member references” is implemented. This allows the use of members after a dot without backticks, e.g. “foo.default”.

Verdict: Not quite ready for prime time. Chris Lattner tweets: “Fwiw, that is the intended design of SE-0071.  It only changes “after the dot”.  You need to use back ticks after [v]ar”

Screen Shot 2016-05-18 at 9.23.41 AM

Screen Shot 2016-05-18 at 9.58.10 AM

Proposal SE-0046. Function parameters now have consistent labelling across all function parameters.

Verdict: Working.

Screen Shot 2016-05-18 at 9.27.00 AM

Proposal SE-0037. “Comments are now treated as whitespace when determining whether an operator is prefix, postfix, or binary. Comments can no longer appear between a unary operator and its argument.”

Verdict: Working.

Screen Shot 2016-05-18 at 9.35.53 AM

Proposal SE-0031: inout now decorates types, not labels

Verdict: Working

Screen Shot 2016-05-18 at 9.39.41 AM