CSC/ECE 517 Fall 2011/ch1 2a sd: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
 
(18 intermediate revisions by 2 users not shown)
Line 1: Line 1:
=Currying=
=Currying=
Currying is a technique used in Computer Science and Mathematics to transform a function with n parameters into a function with one parameter.  This new function would return a function with n-1 parameters.  A function can either be thought of as having n arguments or a function with 1 argument that maps to another function with n-1 arguments.  For example, a function can be defined as f(x, y, z) -> g where it takes in three arguments x, y and z and returns qTo express this in curried form, the function would need to be split into multiple functions with only one argument.  The new function can be written in the form f(x) -> (y -> (z -> q)).  The function f takes in x as an argument and returns another function which takes in y as an argumentThat function then returns another function which takes in z as an argument and returns q.
Currying is a technique used in Computer Science and Mathematics to transform a function with n parameters into a function with one parameter.  This new function would map to another function with n-1 arguments.  For example, we can define a function as add(x, y) -> x + y.  This function takes in two parameters, x and y, and returns x + y.  If we wanted to evaluate add(3, 4) here is how we would do it:
A function, f(x, y, z) -> q, can be expressed in its curried form, F(x) -> (y -> (z -> q)).


Currying can be used in programming to simplify the code and make it easier to read.  This reduces code repetition by combining the common parts of different function into one. 
    add(3, 4) ↦ x + y
    = 3 + 4 = 7


In contrast, there is also uncurryingUncurrying is a technique of transforming a one argument function into a function with many arguments.
The function is evaluated all in one stepThe curried form of this function would be: add(x) -> (y -> x + y).  The add function takes in one parameter, x, and returns another function taking in y.  The second function then returns the result x + y. If we wanted to evaluate add(3, 4) in curried form, the following steps should be taken:


The notion is that a function of n arguments can be thought of as a function of 1 argument that maps to a function of n−1 arguments
    add(3) ↦ (y ↦ x + y)
    = 4 ↦ 3 + y
    = 3 + 4 = 7


The curried function is evaluated in two steps instead of one.  Also, x is treaded like a constant in the second function.
As shown in the given example, the curried and uncurried form of the add function produce the same result.  Another thing to note, a function can be curried but also a curried function can be uncurried.  To transform a curried function into an uncurried one, we just need to reverse the steps.


==Background==
==Background==
Currying was first discovered by Moses Schönfinkel, a Russian Logician, in 1924[http://c2.com/cgi/wiki?CurryingSchonfinkelling] and later re-discovered by Haskel Curry, an American Mathematician and Logician.  Although Schönfinkel was the first to discover it, the process was ultimately named after Curry.  For this reason, some people thought a more appropriate name would be  Schönfinkeling.
Currying was first discovered by Moses Schönfinkel, a Russian Logician, in 1924<ref>http://c2.com/cgi/wiki?CurryingSchonfinkelling</ref> and later re-discovered by Haskel Curry, an American Mathematician and Logician.  Although Schönfinkel was the first to discover it, the process was ultimately named after Curry.  For this reason, some people thought a more appropriate name would be  Schönfinkeling.
 


=Currying in Math=
=Currying in Math=
 
Currying is used throughout Mathematics.  Most notably, currying is used in [http://en.wikipedia.org/wiki/Lambda_calculus lambda calculus].  Lambda calculus borrows the idea that every function can only have one parameter<ref>http://en.wikipedia.org/wiki/Lambda_calculus</ref>.


==Currying v.s. Partial Function==
==Currying v.s. Partial Function==
There is a small distinction between currying and partial functions.  A Partial function simplifies another function by making one or more of its arguments constant.  In contrast a curried function takes in one parameter and returns ...
There is a small distinction between currying and [http://en.wikipedia.org/wiki/Partial_function partial functions].  A Partial function simplifies another function by making one or more of its arguments constant.  Suppose we have a function, f(x, y, z) -> x + y + z.  If we were to curry the function,  we would get f(x) -> (y -> (z -> x + y + z)).  To create a partial function, we can set x, y, and/or z to a constant value.  If we wanted to require x to always be 1, we remove x as a parameter and set it to 1 as follows: f(y, z) -> 1 + y + z.  One thing to point out is curried functions can only have one parameter while partial functions can have one or more<ref>http://en.wikipedia.org/wiki/Partial_function</ref>.


=Currying in Programming=
=Currying in Programming=
Currying is used in several programming languages.
Currying can be used in programming to simplify the code and make it easier to read.  This reduces code repetition by combining the common parts of different function into one.  Many different programming languages used today implement currying.  Currying is most evident in functional programing languages.  Other languages such as java and c++ do not have built in support for currying.  Shown below is a couple of languages and their implementations of currying.
 
==Ruby==
==Ruby==
In ruby 1.9, the curry method was added to procedure objects.  Previous versions of ruby do not have a dedicated curry function.  Here is an example of using the curry function in Ruby [http://www.khelll.com/blog/ruby/ruby-currying/].
In ruby 1.9, the curry method was added to procedure objects.  Previous versions of ruby do not have a dedicated curry function.  Here is an example of using the curry function in Ruby <ref>http://www.khelll.com/blog/ruby/ruby-currying/</ref>.


Suppose we have 3 different functions:  
Suppose we have 3 different functions:  


1.  sum_ints:  this function takes in two arguments, a and b, and determines the sum of all integers between a and b.
1.  product_ints:  this function takes in two arguments, a and b, and determines the product of all integers between a and b.


            sum_ints = lambda do |a,b|
        product_ints = lambda do |a,b|
              s = 0 ; a.upto(b){|n| s += n } ; s  
          s = 1 ; a.upto(b){|n| s *= n } ; s  
            end
        end


2.  sum_of_squares: this function takes in two arguments, a and b, and returns the sum of the square of the integers from a to b.
2.  product_of_squares: this function takes in two arguments, a and b, and returns the product of the square of the integers from a to b.


            sum_of_squares = lambda do |a,b|
        product_of_squares = lambda do |a,b|
              s = 0 ; a.upto(b){|n| s += n**2 } ;s  
          s = 1 ; a.upto(b){|n| s *= n**2 } ;s  
            end
        end


3.  sum_of_powers_of_2: this function takes in two arguments, a and b, and returns the sum of the powers of two from a to b.
3.  product_of_powers_of_2: this function takes in two arguments, a and b, and returns the product of the powers of two from a to b.


            sum_of_powers_of_2 = lambda do |a,b|
        product_of_powers_of_2 = lambda do |a,b|
              s = 0 ; a.upto(b){|n| s += 2**n } ; s  
          s = 1 ; a.upto(b){|n| s *= 2**n } ; s  
            end
        end


We can note that each function follows a similar pattern.  They all use the summation function to sum a group of numbers from a to b.  We can pull this functionality out and write one main function that all three functions will use:
We can note that each function follows a similar pattern.  They all use the product of a sequence of numbers from a to b.  We can pull this functionality out and write one main function that all three functions will use:


         sum = lambda do |f,a,b|
         product = lambda do |f,a,b|
           s = 0 ; a.upto(b){|n| s += f.(n) } ; s  
           s = 1 ; a.upto(b){|n| s *= f.(n) } ; s  
         end
         end


This function takes in three arguments: f, a, and b.  The argument 'f' is the function we want to use on each element in the summation.  The arguments 'a' and 'b' are used to define the lower and upper bound respectively.  Now we can create the curried form of the 'sum' function.
This function takes in three arguments: f, a, and b.  The argument 'f' is the function we want to use on each element in the multiplication sequence.  The arguments 'a' and 'b' are used to define the lower and upper bound respectively.  Now we can create the curried form of the 'product' function.


         currying = sum.curry
         currying = product.curry
   
   
With this currying function we can create the three partial functions defined above.
With this currying function we can create the three partial functions defined above.
         sum_ints = currying.(lambda{|x| x})
 
         sum_of_squares = currying.(lambda{|x| x**2})
         product_ints = currying.(lambda{|x| x})
         sum_of_powers_of_2 = currying.(lambda{|x| 2**x})
         product_of_squares = currying.(lambda{|x| x**2})
         product_of_powers_of_2 = currying.(lambda{|x| 2**x})


==Haskell==
==Haskell==
In Haskell, all functions are in curried form.  In other words, all functions take just one argument.  This notion is mainly hidden from the user.  For instance, we can divide two numbers, 8 and 4, by  calling 'div 8 4'.  The function does not take in two number and return the result as one would think.  In Haskell, the 'div' function is defined as:
In Haskell, all functions are in curried form.  In other words, all functions take just one argument.  This notion is mainly hidden from the user.  For instance, we can divide two numbers, 8 and 4, by  calling 'div 8 4'.  The function does not take in two number and return the result as one would think.  In Haskell, the 'div' function is defined as:


                  div :: int -> int -> int
        div :: int -> int -> int
 
The three integers above represent the first argument, the second argument, and the result respectively.  The division is computed in two steps.  First the function 'div' evaluates the first argument, 8, and returns a function of type 'int -> int'.  This new function is then applied to the second argument, 4, and returns the result of 2 <ref>http://www.haskell.org/haskellwiki/Currying</ref>.
 
==JavaScript==
In javaScript, there is no built-in currying function.  However, we can create a curried function manually by using the idea that methods can return other methods.  For instance, if we have an uncured add function as described below,
 
    var add = function(a, b) {
        return a + b;
    };
 
we can curry the function by returning another function.  The curried form of the add function is shown below <ref>http://extralogical.net/articles/currying-javascript.html</ref>:
 
    var curriedAdd = function(a) {
        return function(b) {
            return a + b;
        };
    };
 
==ML==
ML stands for Metalanguage.  In ML all anonymous functions are curried.  An anonymous function is a function that has no name and can only take one parameter  Shown below is an example of an anonymous function:
 
    val add = (fn x => (fn y => x + y));
 
We can also represent this function in its uncurried form by not using anonymous functions <ref>http://www.svendtofte.com/code/curried_javascript/</ref>:


The three integers above represent the first argument, the second argument, and the result respectively.  The division is computed in two steps.  First the function 'div' evaluates the first argument, 8, and returns a function of type 'int -> int'.  This new function is then applied to the second argument, 4, and returns the result of 2 [http://www.haskell.org/haskellwiki/Currying].
    fun add x y = y + x


=References=
=Conclusion=
[1] http://c2.com/cgi/wiki?CurryingSchonfinkelling
As we discussed in this article, there are many advantages to using currying.
 
Advantages
 
1. Makes code easier to read<br \>
2.  Allows for easy creation of partial functions<br \>
3.  A method can still be executed even if all its parameters are not known.<br \>
4.  Simplifies the method call of functions<br \>
5.  Condenses code by eliminating duplicated statements<br \>


[2] http://www.khelll.com/blog/ruby/ruby-currying/
Currying is used throughout Mathematics and Computer Science. It is the underlying idea behind the programming language Haskel as well as lambda calculus.  Currying is a very powerful tool that, if used correctly, can greatly simplify a function.


[3] http://www.haskell.org/haskellwiki/Currying
=References=
<references />

Latest revision as of 20:48, 30 September 2011

Currying

Currying is a technique used in Computer Science and Mathematics to transform a function with n parameters into a function with one parameter. This new function would map to another function with n-1 arguments. For example, we can define a function as add(x, y) -> x + y. This function takes in two parameters, x and y, and returns x + y. If we wanted to evaluate add(3, 4) here is how we would do it:

   add(3, 4) ↦ x + y
   = 3 + 4 = 7

The function is evaluated all in one step. The curried form of this function would be: add(x) -> (y -> x + y). The add function takes in one parameter, x, and returns another function taking in y. The second function then returns the result x + y. If we wanted to evaluate add(3, 4) in curried form, the following steps should be taken:

   add(3) ↦ (y ↦ x + y)
   = 4 ↦ 3 + y
   = 3 + 4 = 7

The curried function is evaluated in two steps instead of one. Also, x is treaded like a constant in the second function.

As shown in the given example, the curried and uncurried form of the add function produce the same result. Another thing to note, a function can be curried but also a curried function can be uncurried. To transform a curried function into an uncurried one, we just need to reverse the steps.

Background

Currying was first discovered by Moses Schönfinkel, a Russian Logician, in 1924<ref>http://c2.com/cgi/wiki?CurryingSchonfinkelling</ref> and later re-discovered by Haskel Curry, an American Mathematician and Logician. Although Schönfinkel was the first to discover it, the process was ultimately named after Curry. For this reason, some people thought a more appropriate name would be Schönfinkeling.

Currying in Math

Currying is used throughout Mathematics. Most notably, currying is used in lambda calculus. Lambda calculus borrows the idea that every function can only have one parameter<ref>http://en.wikipedia.org/wiki/Lambda_calculus</ref>.

Currying v.s. Partial Function

There is a small distinction between currying and partial functions. A Partial function simplifies another function by making one or more of its arguments constant. Suppose we have a function, f(x, y, z) -> x + y + z. If we were to curry the function, we would get f(x) -> (y -> (z -> x + y + z)). To create a partial function, we can set x, y, and/or z to a constant value. If we wanted to require x to always be 1, we remove x as a parameter and set it to 1 as follows: f(y, z) -> 1 + y + z. One thing to point out is curried functions can only have one parameter while partial functions can have one or more<ref>http://en.wikipedia.org/wiki/Partial_function</ref>.

Currying in Programming

Currying can be used in programming to simplify the code and make it easier to read. This reduces code repetition by combining the common parts of different function into one. Many different programming languages used today implement currying. Currying is most evident in functional programing languages. Other languages such as java and c++ do not have built in support for currying. Shown below is a couple of languages and their implementations of currying.

Ruby

In ruby 1.9, the curry method was added to procedure objects. Previous versions of ruby do not have a dedicated curry function. Here is an example of using the curry function in Ruby <ref>http://www.khelll.com/blog/ruby/ruby-currying/</ref>.

Suppose we have 3 different functions:

1. product_ints: this function takes in two arguments, a and b, and determines the product of all integers between a and b.

        product_ints = lambda do |a,b|
          s = 1 ; a.upto(b){|n| s *= n } ; s 
        end

2. product_of_squares: this function takes in two arguments, a and b, and returns the product of the square of the integers from a to b.

        product_of_squares = lambda do |a,b|
          s = 1 ; a.upto(b){|n| s *= n**2 } ;s 
        end

3. product_of_powers_of_2: this function takes in two arguments, a and b, and returns the product of the powers of two from a to b.

        product_of_powers_of_2 = lambda do |a,b|
          s = 1 ; a.upto(b){|n| s *= 2**n } ; s 
        end

We can note that each function follows a similar pattern. They all use the product of a sequence of numbers from a to b. We can pull this functionality out and write one main function that all three functions will use:

        product = lambda do |f,a,b|
          s = 1 ; a.upto(b){|n| s *= f.(n) } ; s 
        end

This function takes in three arguments: f, a, and b. The argument 'f' is the function we want to use on each element in the multiplication sequence. The arguments 'a' and 'b' are used to define the lower and upper bound respectively. Now we can create the curried form of the 'product' function.

        currying = product.curry

With this currying function we can create the three partial functions defined above.

        product_ints = currying.(lambda{|x| x})
        product_of_squares = currying.(lambda{|x| x**2})
        product_of_powers_of_2 = currying.(lambda{|x| 2**x})

Haskell

In Haskell, all functions are in curried form. In other words, all functions take just one argument. This notion is mainly hidden from the user. For instance, we can divide two numbers, 8 and 4, by calling 'div 8 4'. The function does not take in two number and return the result as one would think. In Haskell, the 'div' function is defined as:

        div :: int -> int -> int

The three integers above represent the first argument, the second argument, and the result respectively. The division is computed in two steps. First the function 'div' evaluates the first argument, 8, and returns a function of type 'int -> int'. This new function is then applied to the second argument, 4, and returns the result of 2 <ref>http://www.haskell.org/haskellwiki/Currying</ref>.

JavaScript

In javaScript, there is no built-in currying function. However, we can create a curried function manually by using the idea that methods can return other methods. For instance, if we have an uncured add function as described below,

   var add = function(a, b) {
       return a + b;
   };

we can curry the function by returning another function. The curried form of the add function is shown below <ref>http://extralogical.net/articles/currying-javascript.html</ref>:

   var curriedAdd = function(a) {
       return function(b) {
           return a + b;
       };
   };

ML

ML stands for Metalanguage. In ML all anonymous functions are curried. An anonymous function is a function that has no name and can only take one parameter Shown below is an example of an anonymous function:

   val add = (fn x => (fn y => x + y));

We can also represent this function in its uncurried form by not using anonymous functions <ref>http://www.svendtofte.com/code/curried_javascript/</ref>:

   fun add x y = y + x

Conclusion

As we discussed in this article, there are many advantages to using currying.

Advantages

1. Makes code easier to read
2. Allows for easy creation of partial functions
3. A method can still be executed even if all its parameters are not known.
4. Simplifies the method call of functions
5. Condenses code by eliminating duplicated statements

Currying is used throughout Mathematics and Computer Science. It is the underlying idea behind the programming language Haskel as well as lambda calculus. Currying is a very powerful tool that, if used correctly, can greatly simplify a function.

References

<references />