// It’s not important what the function does,
// the only thing that matters is the method chaining
// and the types.
func decodeFrontMatter(_ source: String) -> [String: String] {
return source
.split(separator: "\n")
.map(String.init)
.compactMap(decodeKeyValuePair) // String -> (String, String)?
// and so on
}
This is easy to read, piping the source value through a number of transforms. But in the last step (after compactMap) I get an array of tuples that I would like to turn into a dictionary using Dictionary.init(keysAndValues:uniquingKeysWith:). And that cannot be chained any more (?), so I have to introduce a local variable to store the temporary tuple array result and pass that to the dictionary initializer. Is there a way around it, something like this perhaps?
PS. Ah, I see, the dictionary initializer would not type-check as such, as it needs a second argument. Let’s pretend I have some partially applied version of the initializer that only needs the tuple list, then.
infix operator |>: AdditionPrecedence // probably better to define a new precedence group
func |><A, B> (lhs: A, rhs: (A) -> B) -> B {
return rhs(lhs)
}
(like you have in some other languages, e.g. Elixir, F#, ...)
This is what I always do. Also note that in the last step, you don't have to explicitly make a closure to wrap the initialiser, but you can use a function reference as an implicit closure:
Ah, I didn't know this worked with keyword args. You're probably still limited to one-argument functions though, I assume, since Swift doesn't curry by default?
Yeah, I already had the operator defined and was toying with it, but the slight “impedance mismatch” between the functional and method approach bugged me a bit. (When I see |>, I tend to expect function composition using >> instead of method chaining.)
Right. There are libraries (such as Overture) that supply the usual curry and flip, but as I wrote above, I’m still on the fence about the right amount of functional programming in Swift.