Swift: Benefits of Curry Function
The problem is that the example given isn't an example of currying exactly. That's why you don't see any value in it.
This is a better example of currying:
class MyHelloWorldClass {
//Function that takes two arguments
func concatenateStrings(string1: String, string2: String) {
return "\(string1)\(string2)"
}
//Curried version of concatenateStrings that takes one argument.
func helloWithName(name: String) -> String {
return concatenateStrings("hello, ", name)
}
}
This is a better example of how function variables are curried functions in Swift: http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/
What is 'Currying'?
Currying is when you break down a function that takes multiple arguments into a series of functions that each take only one argument. Here's an example in JavaScript:
function add (a, b) {
return a + b;
}
add(3, 4); // returns 7
This is a function that takes two arguments, a and b, and returns their sum. We will now curry this function:
function add (a) {
return function (b) {
return a + b;
}
}
This is a function that takes one argument, a
, and returns a function that takes another argument, b
, and that function returns their sum.
add(3)(4); // returns 7
var add3 = add(3); // returns a function
add3(4); // returns 7
- The first statement returns 7, like the
add(3, 4)
statement. - The second statement defines a new function called
add3
that will
add 3 to its argument. (This is what some may call a closure.) - The third statement uses the
add3
operation to add 3 to 4, again
producing 7 as a result.
Need help in understanding types (based on curry)
I believe the source of your confusion is this passage:
the curry function takes function f a b
Not really: curry
takes a function, and that function is f
. As for a
and b
, they are arguments that are passed to the curried function. It is easier to see that by either adding a pair of superfluous parentheses, to make the partial application more evident...
(curry f) a b = f (a,b)
... or by shifting a
and b
to the right-hand side with a lambda:
curry f = \a b -> f (a,b)
f
is a function that takes a pair -- note that we give it a pair, (a,b)
. curry f
, on the other hand, takes the two arguments separately. That being so, the type of curry
is indeed:
curry :: ((a, b) -> c) -> (a -> b -> c)
Swift - A function with double parentheses?
As mentioned in the comments this would be referred to as Curried Functions
.
Basically it gives you the ability to dynamically create functions with more specificity than a function would have if you sent in all the params.
Example time (this is a rather dumb example but it should give you an idea of what currying does)
func addNumbers(a a: Int, b: Int) -> Int {
return a + b
}
func addNumbers(a a: Int)(b: Int) -> Int {
return a + b
}
//usage normal function
var two = addNumbers(a:1, b:1)
var three = addNumbers(a:1, b:2)
var four = addNumbers(a:1, b:3)
//usage curried function
var addOne = addNumbers(a:1)
var two = addOne(b:1)
var three = addOne(b:2)
var four = addOne(b:3)
So if you have some problem that you know will be solved with one value for one of your params in some specific case but another value in another situation you can save yourself from sending in those parameters and instead just create the function where it will be used.
Again as I wrote above this was a dumb example but it can be very useful when writing a REST api as an example. Where you have the same functions applied to a lot of different types which can be saved in the same general way.
Another usage example Logger implemented with Currying
In your example the function for mapping objects can be applied first and then the created mapping function can be applied to the sources that should be mapped.
You can read more about it here and here
Are these two curry function implementations equal?
Yes, they are identical. If you compile:
object Test {
def curry[A,B,C](f: (A, B) => C): A => (B => C) =
(a: A) => f(a, _)
def curry2[A,B,C](f: (A, B) => C): A => (B => C) =
(a: A) => (b: B) => f(a, b)
}
with -Xprint:typer
, you get the intermediate abstract syntax tree:
[[syntax trees at end of typer]]
package <empty> {
object Test extends scala.AnyRef {
def <init>(): Test.type = {
Test.super.<init>();
()
};
def curry[A, B, C](f: (A, B) => C): A => (B => C) = ((a: A) => ((x$1: B) => f.apply(a, x$1)));
def curry2[A, B, C](f: (A, B) => C): A => (B => C) = ((a: A) => ((b: B) => f.apply(a, b)))
}
}
During the "typer" stage, when the compiler assigns types to everything, it realizes that the _
(now named x$1
) must be type B
.
Related Topics
Add a File Generated by Run Script into The Test Target Compilation List in Xcode
Xcode 6.1 Swift Extensions - Sourcekit Service Crash
Swift Video to Document Directory
Swift Getnameinfo Unreliable Results for Ipv6
Swiftui Vertically Misaligned Text
Create Custom Action in a Class for Use in Interface Builder
Swift 4 JSONdecoder Optional Variable
My UIcollectionview Does Not Scroll Smoothly Using Swift
Swift Sha256 Encryption Returns Different Encrypted String Compare to Objective C
Alamofire Request Not Working in Swift 4 Project
Lldb for Swift: Access Computed Property or Perform Function Call in Type Summary Python Script
How to Replace My .Xib File with Pure Swift 3
Compiling for iOS 10.3, But Module 'swiftuicharts' Has a Minimum Deployment Target of iOS 13.0
How to Use Nscalendar Range Function Within Calendar
Dynamically Set Properties from Dictionary<String, Any> in Swift
Delete Tableview Cell, and Remove Data from Firebase
Why Are Implicitly Unwrapped Variables Now Printing Out as Some(...) in Swift 4.1