Evolve or die: The Swift storm rages on

Generic enhancements for Swift 3.0

I loved this post, which summarizes where things are and where things may yet go with respect to generics. I’ve posted before about several of these wish-lish items and this response by Doug Gregor to a post by Matthew Johnson covers not only what may be coming down the line (or not) but also why (or why not).

Bring me a Higher Love Kinded Type

There’s a long discussion about Higher Kinded Types such as monads, functors, and so forth ranging on-list. This isn’t something I’m particularly into and it reads to me as, “This stuff is cool” “Give some practical examples of how Swift coding would benefit.”  “But this stuff is cool.” I think I’m entirely missing the point.

Property Behaviors

Here’s a particularly cool proposal from Joe Groff that abstracts out common implementation patterns for annotating properties. This approach would allow the team to develop a library of common behaviors (vs hard-coding them into the compiler).

The behaviors could be expanded, tweaked, and used upon demand by annotating properties with parenthesized keywords. Not just lazy but lazy on steroids. I’m feeling very +1 on this and I learned the metasyntactic phrase “runcible“. Win.

Refactoring Code

I’ve now spent several hours modernizing code. Of all the issues, the var ones ended up being the trickiest to deal with, for example:
public func imageFromVImageBuffer(var buffer: vImage_Buffer) -> UIImage? {
when using Accelerate, which translated to
public func imageFromVImageBuffer(buffer: vImage_Buffer) -> UIImage? {
    var buffer = buffer
Not a huge deal, but…you know, ugly. I had to fix guard vars, if vars, for vars, case vars, etc.
A few interesting situations with ++ and — popped up, and were generally solved either with extra variables or defer statements. The original in this case was return (index, self[index++]):
defer {index = index.successor()}
return (index, self[index])
Of the 3.0 changes,  the var parameter ones took the most time, followed by ++/–.
The for-loop ones were trivial and I had exactly one (1) keyword `escape` issue that I’ll delay fixing until the language changes. To be fair, I did have to kill and refactor a few dozen currying calls, but that’s to be expected since the code was for a chapter that introduced the concept of currying. I don’t consider those to be common applications. Call it 3, maybe 4, *real* (useful, realworld) curries among many calls. There’s still plenty of code to review though. All said, though, the process was less horrible than it might have been.

One Comment

  • Higher-kinded types enable lots of very useful functions. Say you have a list of futures of results (List[Future[String]], using Scala notation) from a bunch of asynchronous operations. Since you know you want to work with all of the results, it’s easier to work with a Future[List[String]]. Since you know both Future and List are monads, you know that you can just calla function called “sequence” to flip the order. If x = List[Future[String]], x.sequence is Future[List[String]]. And that works with any monad – Option[List[String]] List[Option[String]], etc. Or do you have a function that takes and returns a string? Need a function that takes and returns an Option[String]? Or List[String]? Or any other Monad[String]? You know you can transform that function without having to write code for each and every monad. And error handling is easier, too, both for operations where you want to accumulate errors (say, form handing, where you want to know all the errors) or you want to short-circuit a series of operations.