CSC/ECE 517 Fall 2011/ch1 2a bi

From Expertiza_Wiki
Jump to navigation Jump to search

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 = &divide.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 &divide...prints 21
       print $halve(42);       # calls &divide...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.

Partial Functions Versus Currying

Partial functions<ref>Partial Function</ref> are primarily used to produce new definitions of function where one or more arguments of a function are fixed. In contrast, in the currying technique the arguments are not actually fixed, instead the function is evaluated as the function arguments stream in.

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);

Advantages

The advantage of currying is that we can bind one argument and leave the remaining argument(s) free. This is useful to pass function around, in situations where all the arguments are not immediately available. Also when programming in a functional style, one often bind arguments to generate new functions from the old definitions of the functions.

References

<references/>

External Links

  1. Currying
  2. Scala Currying
  3. Article on Scala Currying
  4. Procs in Ruby
  5. Currying in Ruby
  6. Article on the currying concept