MICHAEL BATES

iOS and Web Development with Passion and Precision


Blog Posts Subscribe →

Instance Methods are Curried Functions in Swift

Permalink

Update 2017-09-04
This behavior will be changed in a future version of Swift whenever proposal SE-0042 is implemented, but as of Swift 4.0 it’s still available. Check out the proposal for more details and the rationale behind this change.

This is a really neat technical detail of Swift: under the hood, instance methods can be accessed directly through the class as a curried function. If you don’t know what function currying is, it’s something best explained through example. Here is the same function in curried and non-curried forms:

func normalFunc(a: Int, b: Int) -> Int
func curryFunc(a: Int) -> (b: Int) -> Int

That’s a function returning a function returning an Int. Those familiar with Javascript will recognize this from the ability to partially apply parameters using .bind(). So, when I say that instance methods are curried class methods, I mean that these two method calls are identical:

let message = "spicy curry is tasty!"
message.hasPrefix("spicy")
String.hasPrefix(message)("spicy")

Ole Begemann tipped me off to a really compelling use case for this feature. He shows how to make a type-safe target-action pattern that does not rely on selectors or Objective-C’s dynamic message dispatcher. If you’re not sure why that’s so cool, he offers this tidbit of wisdom:

This pattern is often better than using plain closures for callbacks, especially when the receiving objects has to hold on to the closure for an indeterminate amount of time. Using closures often forces the caller of the API to do extra work to prevent strong reference cycles. With the target-action pattern, the object that provides the API can do the strong-weak dance internally, which leads to cleaner code on the calling side.

Check out Begemann’s post for more!

Functional Complements to Swift, Part 1

Permalink

In exploring ways to use functional programming concepts in Swift, I’ve made some additions to its basic language features. This is part of an ongoing series about functional components I’ve added to Swift.

Here, I’ve added a function to Array called partition. In short, the function will partition the Array into a Dictionary based on a function which takes an Element of the Array and returns its corresponding Key into the Dictionary.

extension Array {
  func partition<Key>(key: (Element)->Key) -> [Key: [Element]] {
  var groups = [Key: [Element]]()
    for element in self {
      let key = key(element)
      var group = groups[key] ?? [Element]()
      group.append(element)
      groups[key] = group
    }
    return groups
  }
}

Now we can use the method to partition our arrays!

let nums = [1,2,3,4,5,6,7,8,9,10]
nums.partition { n in
	n % 2 == 0 ? "even" : "odd"
}

This will give us the following Dictionary.

["odd": [1, 3, 5, 7, 9], "even": [2, 4, 6, 8, 10]]

Without our method, we could could achieve the same thing using Array’s reduce(initial: combine:), like so.

let groups = ["odd": [Int](), "even": [Int]()]
nums.reduce(groups) { (var groups, n) in
  let key = n % 2 == 0 ? "even" : "odd"
  groups[key]?.append(n)
  return groups
}

Our partition is, obviously, much more terse and readable. I haven’t needed to use this method in any projects yet, but I can see it being very useful somewhere.

Check out the full code.