(un)zurry
16 Oct 2019 ⇐ Notes archive(This is an entry in my technical notebook. There will likely be typos, mistakes, or wider logical leaps — the intent here is to “let others look over my shoulder while I figure things out.”)
(un)zurry
moves arguments in and out of Void
-accepting closures in the same way (un)curry
moves arguments in and out of tuples. Concretely, here’s how they’re defined:
The former is often helpful when staying point-free with functions that are close, but not quite the right shape you need. e.g. mapping unapplied method references:
Eep.
Let’s try to make this work.
We’d like [Int].sorted
to have the form [Int] -> [Int]
, and since SE-0042 got rejected, we have to chisel it down on our own.
First, let’s flip the first two arguments and then address the rogue ()
.
Getting closer—this is where zurry
can zero out the initial Void
for us.
zurry(flip([Int].sorted)) // (Array<Int>) -> Array<Int>
Wicked, now we can return to our original example:
[[2, 1], [3, 1], [4, 1]].map(zurry(flip([Int].sorted))) // [[1, 2], [1, 3], [1, 4]]
.
Dually, unzurry
shines when you’re working against a () -> Return
interface, that isn’t @autoclosure
’d, and you only have a Return
in hand. Instead of opening a closure, you can pass along unzurry(yourReturnInstance)
and call it a day.
The Point-Free folks link to Eitan Chatav’s post where he introduced the term and shows how function application is a zurried form of function composition (!).