CSC/ECE 517 Fall 2011/ch1 2a bi
Introduction
Currying is a function transformation supported by some programming languages. It transforms a function that accepts n parameters and generates from it, one of more functions with some parameter values already filled in. These broken down functions can then be called in a chain to obtain a result equivalent to that obtained by calling the original function.
History and Definition
Currying has its origins in the mathematical study of functions. It was observed by Frege in 1893 that it suffices to restrict attention to functions of a single argument. For example, for any two parameter function f(x,y), there is a one parameter function f' such that f'(x) is a function that can be applied to y to give (f'(x))(y) = f (x,y). This corresponds to the well known fact that the sets (AxB -> C) and (A -> (B -> C)) are isomorphic, where "x" is cartesian product and "->" is function space. It was independently re-discovered by Moses Schönfinkel [REFERENCE] and by Haskell Curry [reference] and made it into the Haskell functional programming language as a primary feature.[Reference] In essence, the currying process takes a function of two parameters and returns a pointer to a function of one parameter. The function body itself doesn't change. The newly returned function pointer can then be called with the parameter that was left out in the first transformation.
Another way to think about this, is in terms of the default values for function parameters that most programming languages permit. Default argument is the part of function declaration and it tells compiler what value to pass for an argument if the programmer deliberately misses the argument when calling the function. In the common case that many arguments are almost always the same, this saves the programmer's time and effort required to remember and specify all arguments. Default arguments are useful in situations where some arguments always have the same value. The default parameter values however are constricting, in that the program is only allowed to use those values in case the function call is missing a particular parameter value. Currying enables us to overcome this restriction by essentially generating additional function definitions for the same underlying function with different default values. Consider a C++ function, sample_test(bool test = false, int data), here the default value of the parameter test is set to 'false' and will remain so for the life of the program. However with currying, we can transform the function to: sample_test_1(1), sample_test_1(1) can then be called either as sample_test_1(true, 1) or sample_test_1(false, 1).
Currying In Modern Languages
Currying, as a language feature, has made the cross over the functional programming languages<ref>Functional Programming Languages</ref> to imperative programming languages. Languages such as Scala <ref> Scala Programming Language</ref> , Ruby<ref>The Ruby Programming Language</ref>, Perl <ref>The Perl Programming Language</ref> and Groovy<ref>The Groovy Programming Language</ref> support currying. Functional programs such as Haskell <ref>The Haskell Progamming Language</ref>have always supported it. We will look at how to use this feature in a few modern languages in the sections below.
Currying In Ruby
Ruby is a pure object oriented programming language that has built in support for currying. Ruby supports currying mainly by using 'Proc' objects. Proc objects are blocks of code that have been bound to a set of local variables. Once bound, the code may be called in different contexts and still access those variables. The Proc class implements a 'curry ' function that can be called on any function. The curry function returns a curried proc. A curried proc receives some arguments. If a sufficient number of arguments are supplied, it passes the supplied arguments to the original proc and returns the result. Otherwise, it returns another curried proc that takes the rest of arguments. For e.g.
code_blob = Proc.new {|x, y, z| z= x+y} code_blob.curry[1, 2]
The Ruby kernel function lambda also returns a Proc object and hence can call the curry function as well.
code_blob = lambda {|x, y, z| z= x+y} code_blob.curry[1, 2]
Currying In Perl
The Perl6::Currying module is used to implement currying in Perl. In Perl 6 any subroutine can be "partially bound", i.e., some of its arguments can be supplied and thereby create another subroutine that calls the original with those arguments automatically supplied. Subroutine parameters are partially bound by calling the prebind method on the subroutine. This method call returns a reference to a new subroutine that calls the original subroutine, inserting into its argument list the prebound arguments. For example:
sub divide ($numerator, $denominator) { return $numerator / $denominator; } my $halve = ÷.prebind(denominator=>2);
Having prebound the denominator, if we now call the subroutine referred to by $halve the effect is to call divide with an automagically supplied denominator of 2. That is:
print divide(42,2); # calls ÷...prints 21 print $halve(42); # calls ÷...prints 21
Currying In Scala
Scala is a modern virtual machine based language that has built-in support for currying. A function that is called with a lesser number of parameters than specified by the function definition automatically returns a curried version of the function. The curried function can later by called by passing the parameters that were left out. For e.g.
def modN(n: Int)(x: Int) = ((x % n) == 0) modN(2) // returns a curried version of modN.
Usage
The currying mechanism is essentially to provide a means for dynamic function creation. It allows the programmer to write cleaner code. Its primary use is when one of the function parameters has a fixed set of values while the rest of the parameters change. Unlike default values for function parameters, currying allows the programmer to dynamically generate function prototype with different baked in default values for a limited set of the function parameters. For, e.g., let consider the function that calculates an individual's tax:
float final_tax(float fed_tax_rate, float state_tax_rate, float count_tax_rate, int income) { return tax // calculations go here
}
The tax rate for each state is different and sometimes even county tax_rates within the same state are different. A clean way of coding this would be to generate functions computing taxes for each state, for, e.g., the curried curried function
float ca_final_tax(float count_tax_rate, int income) {
// return final_tax
}
float final_tax;
ca_final_tax = final_tax(33.33, 9.75);
final_tax = ca_final_tax(2.3, 80000);
References
<references/>
Links
http://en.wikipedia.org/wiki/Currying
http://www.codecommit.com/blog/scala/function-currying-in-scala
http://brizzled.clapper.org/id/102/index.html
http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls#Procs