Summary
Scala makes it straightforward for developers to specify new control structures that feel like natural parts of the language. Function currying is one technique that allows Scala to provide such natural programming constructs. Daniel Spiewak discusses function currying and its uses in a recent article.
Advertisement
One of Scala's benefits is that it allows a developer to create control structures that, while not part of the language, feel as though they were. Such control structures make programs more natural to read.
One way Scala supports such natural-looking constructs is its implementation of currying, a technique that allows the transformation of a multi-argument method into a method with a single argument. The new single-argument method returns another method, with one argument, which is the next argument in the original method's argument list.
In a recent article, Function Currying in Scala, Daniel Spiewak explains how function currying works, and illustrates its benefits:
The currying process transforms a function of two parameters into a function of one parameter which returns a function of one parameter which itself returns the result. In Scala, we can accomplish this like so:
def add(x:Int, y:Int) = x + y
add(1, 2) // 3
add(7, 3) // 10
And after currying:
def add(x:Int) = (y:Int) => x + y
add(1)(2) // 3
add(7)(3) // 10
Spiewak also shows Scala's idiomatic syntax for curried functions:
We can shorten our curried definition to something more like this:
def add(x:Int)(y:Int) = x + y
add(1)(2) // 3
add(7)(3) // 10
While at first such transformations may seem merely syntactic sugar, Spiewak points out several uses of function currying in the article
Of course, it’s not very apparent as to why this is a good idea. All we’ve really accomplished is eliminate the second parameter and move it into another function. This is a big deal in languages like Haskell which only allow a single parameter, but Scala doesn’t have this restriction...
It turns out that the best rationale for using currying has to do with general and specialized functions. It would be nice to define a function for the general case, but allow users to specialize the function and then used the specialized version on different data sets.
In the article, Spiewak illustrates the use of currying in the case of partially applied functions. What do you think of function currying in Scala?
Geez, this is awesome! If I ever want to add 5 to two other integers, I can save typing by going
addFive(3,1)
instead of
add(5,3,1)
Oops - look like it's not only slightly confusing, it's extra typing.
Seriously, why are all the functional programming tutorials full of useless pathetic examples? I'd like to learn some FP, I can imagine it being better in multi-core worlds, but so far I'm completely unimpressed by every example / tutorial I've ever seen.
> Seriously, why are all the functional programming > tutorials full of useless pathetic examples?
I think it's sad in the online and print publishing worlds that it takes something like the Python Cookbook or maybe Best of Ruby Quiz to show interesting, useful examples of currying. Not that I'm an FP expert. (And I barely know Scala.) But, yeah, it's hard to mentally extrapolate from the same old addFive examples to something that makes you say, "All right. Now you're cooking."
Thanks for the Hole in the Middle example - it's a good one.
I did something much like this in Java, eerily similar to his blog. There was some terrible SQL query code to return a List of objects, copied and pasted all over (with minor inconsistencies and bugs in closing the statements and connections). The only "variables" were
1) the query 2) converting a ResultSet to an Object
So, like in the Hole in the Middle article, I created an interface (ignore the extra parameter, it was needed somewhere once)
public interface IRSable<T> {
public T fromResultSet(ResultSet rs, Object extra) throws SQLException ; }
and just passed in implementations of it, plus the query.
Personally, I didn't find the extra overhead of defining an interface and creating the classes all that burdensome. (And I could have used reflection to shortcut) But maybe if I were doing things like this a lot...
Don't shoot the message because of the example! (or some other such mangled saying ;-)
My poster-child example for a practical use of currying is sales tax. In the state where I live, the sales tax is made up of a state portion and a local portion, along with a limit on one of them. So you could write a sales tax function with four arguments: statePct, localPct, limit, and saleAmount.
Currying allows the definition of a specialized function by fixing some, but not all, of the arguments of a more general function. So, in this case, a function for the sales tax at a specific locality is obtained by currying over the first three arguments.
It seems quite natural to say, "The sales tax function for Bigtown is the general state sales tax function with the following three values fixed:..."
Thank you, Joel. Your Bigtown sales tax gave me an insight, FWIW:
Curry is to Function as Instantiate is to Class. Fixing some arguments while currying a function is like setting some fields while instantiating a class.
Or perhaps: Currying is to Function as Subclassing is to Class. Fixing some arguments while currying a function is like specializing some behavior while subclassing a class.
This is all very roughly speaking, of course, and I need to ponder it some more.
> Or perhaps: Currying is to Function as Subclassing is to > Class. Fixing some arguments while currying a function is > like specializing some behavior while subclassing a > class. > > This is all very roughly speaking, of course, and I need > to ponder it some more.
No, that is a good comparision. You will find currying as just happening in OO, as a special case of subclassing. So it is usable as a metapher.
Consider each function being a subclass of, say, Function implementing the static method apply.
(pseudocode)
class MyFunction extends Function { public static SomeType apply(firstParam, secondParam) { // some code } }
class MyCurriedFunction extends MyFunction { public static SomeType apply(secondParam) { apply( FIX_VALUE, secondParam ) } }
result = MyCurriedFunction.apply( aValue )
Or a more rudimentary, instance based example:
class MyFunction extends Function { protected firstParam protected secondParam
MyFunction(first, second) { firstParam = first secondParam = second }
public Object apply() { // some code working with firstParam, secondParam } }
myFunc = new MyFunction( valueOne, valueTwo ) result = myFunc.apply()
I think instantiation and subclassing are reasonable analogies, at a first approximation. The core idea of specializaton/customization is one that shows up in many ways: instantiation, subclassing, currying, setting properties on a component, etc.
One interesting difference is that instantiation is an all-or-nothing affair, in that you have to supply all arguments for a valid constructor. It is certainly possible to create a subclass that fixes part, but not all, of the state/parameterization of the parent class, but I haven't seen that discussed or practiced very often. (Perhaps because of the amount of boilerplate required?)
But that sort of partial specialization seems to be a natural consequence of being able to curry a function with little "baggage".
Aside: To me, that's one of the huge benefits of studying multiple languages; learning something that's easy to express in one language may get one over the static friction of using the idea in a language which requires more baggage.
Flat View: This topic has 25 replies
on 2 pages
[
12
|
»
]