CSC/ECE 517 Fall 2007/wiki1 3 c1: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
mNo edit summary
mNo edit summary
Line 5: Line 5:
Currying is a transformational technique in functional programming.  
Currying is a transformational technique in functional programming.  


Given a function f of type f : (X x Y) -> Z , then currying it makes a function curry(f):(Y -> Z) . That is, curry(f) takes an argument of type X and returns a function of type Y -> Z .
Given a function f of type f : (X x Y) -> Z , then currying it makes a function  
curry(f):(Y -> Z) . That is, curry(f) takes an argument of type X and returns a
function of type Y -> Z .


In ordinary words, currying says "if you fix some arguments of a function, you get a new function of the remaining arguments". For example, if function 'power(x,y)' stands for the calculating 'x raised to the power of y' then, square(x), cube(x) are other functions that implicitly fix one argument of y to either 2 or 3 for square and cube functions respectively.
In ordinary words, currying says " if you fix some arguments of a function, you
get a new function of the remaining arguments". For example, if function 'power(x,y)'
stands for the calculating 'x raised to the power of y' then, square(x), cube(x)
are other functions that implicitly fix one argument of y to either 2 or 3 for  
square and cube functions respectively.


The practical motivation for currying is that very often the functions you get by supplying some but not all of the arguments to a curried function are useful; for example, many languages have a function or operator similar to plus_one. Currying makes it easy to define these functions.
The practical motivation for currying is that very often the functions you get by
supplying some but not all of the arguments to a curried function are useful; for
example, many languages have a function or operator similar to plus_one. Currying
makes it easy to define these functions.


Some programming languages have built-in syntactic support for currying, where certain multi-argument functions are expanded to their curried form; notable examples are ML, Haskell and Ruby. Any language that supports closures can be used to write curried functions.
Some programming languages have built-in syntactic support for currying, where
certain multi-argument functions are expanded to their curried form; notable  
examples are ML, Haskell and Ruby. Any language that supports closures can be
used to write curried functions.
 
Now lets get a little mathematical since 'Currying' has been borrowed from
Mathematics


Now lets get a little mathematical since 'Currying' has been borrowed from Mathematics
The math concept is simple:
The math concept is simple:


Line 22: Line 36:
lambda { |a| lambda { |b, c| ... } }
lambda { |a| lambda { |b, c| ... } }


In other words, a function’s arguments can be broken down the way liked by the programmer. We can apply a three-argument function to two arguments to get a one-argument function back. The name "currying" was coined by Christopher Strachey in 1967, is a reference to logician Haskell Curry.
In other words, a function’s arguments can be broken down the way liked by the programmer.  
We can apply a three-argument function to two arguments to get a one-argument function back.  
The name "currying" was coined by Christopher Strachey in 1967, is a reference to  
logician Haskell Curry.


Currying can be done explicitly with lambdas—say we want to curry two arguments into a three-argument function.
Currying can be done explicitly with lambdas—say we want to curry two arguments  
into a three-argument function.


lambda { |c| oneArgFunc( 1, 2, c ) }
lambda { |c| oneArgFunc( 1, 2, c ) }
Line 36: Line 54:


'''Example 1'''
'''Example 1'''
Let us consider a site which allows us to play music files. Now, for each music file we play, the relevant information to be passed to play the system is Album Name, Track Number and Player to be used by that site.
Let us consider a site which allows us to play music files. Now, for each music file we play,  
Let’s consider a scenario where a music site uses only one type of player every time. Let’s say the sites and player is – Mp3 Site (Jukebox Player). Instead of passing the same Player Name every time to the site, we can curry the player Name in the function Play and thus we’ll be sending the only minimum necessary parameters required to play the file while the site-specific information, i.e. the player name will be curried.
the relevant information to be passed to play the system is Album Name, Track Number and Player  
to be used by that site.
Let’s consider a scenario where a music site uses only one type of player every time. Let’s say  
the sites and player is – Mp3 Site (Jukebox Player). Instead of passing the same Player Name  
every time to the site, we can curry the player Name in the function Play and thus we’ll be  
sending the only minimum necessary parameters required to play the file while the site-specific  
information, i.e. the player name will be curried.


def play(albumname,songname,player)
def play(albumname,songname,player)
Line 59: Line 83:
mp3site.call("MLTR", "Track 11")
mp3site.call("MLTR", "Track 11")


In real time scenario, we can put in the actual code which plays the requested file in the function 'play'. The primary purpose of the code is to show that we have all the values required to play the file.
In real time scenario, we can put in the actual code which plays the requested file  
in the function 'play'. The primary purpose of the code is to show that we have all  
the values required to play the file.


'''Example 2'''
'''Example 2'''
The following program illustrates the concept of Currying using a simple example of a basic calculator. The method calculator accepts two operands var1 & var2 performs the operation specified by 'op' on the two operands and returns the result.
The following program illustrates the concept of Currying using a simple example of a basic calculator.  
The method 'calculate' thus accepts 3 arguments. Now, calling this method again and again would lead to poor readbility. Instead by implementing currying we can improve the readability of the code.  
The method calculator accepts two operands var1 & var2 performs the operation specified by 'op' on the  
In the following code we have made use of the 'calculate' method with currying as well as without using curring. Places where 'calculate' is called using calculate(3,+,4) are instances where currying is not used.Places where either of 'add','sub','mul','div' have been used implements currying.  
two operands and returns the result.
The method 'calculate' thus accepts 3 arguments. Now, calling this method again and again would lead to  
poor readbility. Instead by implementing currying we can improve the readability of the code.  
In the following code we have made use of the 'calculate' method with currying as well as without using  
curring. Places where 'calculate' is called using calculate(3,+,4) are instances where currying is not  
used.Places where either of 'add','sub','mul','div' have been used implements currying.  


definition of 'calculate' method
definition of 'calculate' method
Line 102: Line 133:
'''[[Features of Currying]]'''
'''[[Features of Currying]]'''


1. The above examples illustrate that currying helps improve readability of code as it allows us to pass lesser number of arguments to the functions thus making the code easier to understand.
1. The above examples illustrate that currying helps improve readability of code as it allows  
  us to pass lesser number of arguments to the functions thus making the code easier to understand.
   
   
2. The reliability of the code, which is very essential for the reliability of th whole software application increases. This is because a major contributing factor of Software Reliability problems is the complexity of the underlying code. Currying tries to reduce this complexity by fixing the variables which will only take a fixed value and thus should not be left dangling for that particular function. For large applications, involving a lot of functions and variables - currying will be helpful.  
2. The reliability of the code, which is very essential for the reliability of th whole software  
  application increases. This is because a major contributing factor of Software Reliability problems
  is the complexity of the underlying code. Currying tries to reduce this complexity by fixing the  
  variables which will only take a fixed value and thus should not be left dangling for that particular
  function. For large applications, involving a lot of functions and variables - currying will be helpful.  


3. The output of the code does not changes with currying. By fixing the parameters, we are only trying to avoid passing constant or redundant information every time with the function call. By using currying, the results of the code is not modified.
3. The output of the code does not changes with currying. By fixing the parameters, we are only trying to  
  avoid passing constant or redundant information every time with the function call. By using currying,
  the results of the code is not modified.

Revision as of 23:50, 13 September 2007

Currying

Currying is a transformational technique in functional programming.

Given a function f of type f : (X x Y) -> Z , then currying it makes a function curry(f):(Y -> Z) . That is, curry(f) takes an argument of type X and returns a

function of type Y -> Z .

In ordinary words, currying says " if you fix some arguments of a function, you get a new function of the remaining arguments". For example, if function 'power(x,y)' stands for the calculating 'x raised to the power of y' then, square(x), cube(x) are other functions that implicitly fix one argument of y to either 2 or 3 for square and cube functions respectively.

The practical motivation for currying is that very often the functions you get by supplying some but not all of the arguments to a curried function are useful; for example, many languages have a function or operator similar to plus_one. Currying makes it easy to define these functions.

Some programming languages have built-in syntactic support for currying, where certain multi-argument functions are expanded to their curried form; notable examples are ML, Haskell and Ruby. Any language that supports closures can be used to write curried functions.

Now lets get a little mathematical since 'Currying' has been borrowed from Mathematics

The math concept is simple:

lambda { |a, b, c| ... }

lambda { |a| lambda { |b| lambda { |c| ... } } } or

lambda { |a| lambda { |b, c| ... } }

In other words, a function’s arguments can be broken down the way liked by the programmer. We can apply a three-argument function to two arguments to get a one-argument function back. The name "currying" was coined by Christopher Strachey in 1967, is a reference to logician Haskell Curry.

Currying can be done explicitly with lambdas—say we want to curry two arguments into a three-argument function.

lambda { |c| oneArgFunc( 1, 2, c ) }

Two arguments curried in, one argument still dangling.

Getting back to Ruby, Currying in Ruby is pretty straight forward. Typically you use the 'lambda' method to curry the basic function to create new functions.

Let us illustrate this concept further with the help of two examples.

Example 1 Let us consider a site which allows us to play music files. Now, for each music file we play, the relevant information to be passed to play the system is Album Name, Track Number and Player to be used by that site. Let’s consider a scenario where a music site uses only one type of player every time. Let’s say the sites and player is – Mp3 Site (Jukebox Player). Instead of passing the same Player Name every time to the site, we can curry the player Name in the function Play and thus we’ll be sending the only minimum necessary parameters required to play the file while the site-specific information, i.e. the player name will be curried.

def play(albumname,songname,player)

     @albumname = albumname
     @Trackname = songname
     @player = player
     puts "The album is #{@albumname} Track is #{@Trackname} and Player is #{@player}"
 end

Using Curying mp3site = lambda{|albumname,songname| play(albumname,songname,"Jukebox")}

Input Without Using Currying play("The Best of Bryan Adams", "Track 7", "Jukebox") play("MLTR", "Track 1"," Jukebox ") play("MLTR", "Track 11"," Jukebox ")

Input Using Currying mp3site.call("The Best of Bryan Adams", "Track 7") mp3site.call("MLTR", "Track 1") mp3site.call("MLTR", "Track 11")

In real time scenario, we can put in the actual code which plays the requested file in the function 'play'. The primary purpose of the code is to show that we have all the values required to play the file.

Example 2 The following program illustrates the concept of Currying using a simple example of a basic calculator. The method calculator accepts two operands var1 & var2 performs the operation specified by 'op' on the two operands and returns the result. The method 'calculate' thus accepts 3 arguments. Now, calling this method again and again would lead to poor readbility. Instead by implementing currying we can improve the readability of the code. In the following code we have made use of the 'calculate' method with currying as well as without using curring. Places where 'calculate' is called using calculate(3,+,4) are instances where currying is not used.Places where either of 'add','sub','mul','div' have been used implements currying.

definition of 'calculate' method

def calculate(var1,op,var2)     
  if op == '+'
    return puts "The Result of addition is      : #{var1+var2}"
  elsif op == '-'
    return puts "The Result of subtraction is   : #{var1-var2}"
  elsif op == '*'
    return puts "The Result of multiplication is: #{var1*var2}"
  elsif op == '/'
    return puts "The Result of division is      : #{var1/var2}"
  else
    return puts "wrong choice ! "
  end
end 
 

Following 'calculate' method calls are without using currying

 calculate(3,'+',4)
 calculate(4,'-',5)
 calculate(4,'*',2)
 calculate(4,'/',2)

Currying Implementation using 'lambda'

 add = lambda {|x , y| calculate(x,'+',y)}
 sub = lambda {|x , y| calculate(x,'-',y)}
 mul = lambda {|x , y| calculate(x,'*',y)}
 div = lambda {|x , y| calculate(x,'/',y)} 

Following method calls are by using currying

 add.call(3,4)
 sub.call(4,5)
 mul.call(4,2)
 div.call(4,2)

Features of Currying

1. The above examples illustrate that currying helps improve readability of code as it allows

  us to pass lesser number of arguments to the functions thus making the code easier to understand.

2. The reliability of the code, which is very essential for the reliability of th whole software

  application increases. This is because a major contributing factor of Software Reliability problems
  is the complexity of the underlying code. Currying tries to reduce this complexity by fixing the 
  variables which will only take a fixed value and thus should not be left dangling for that particular
  function. For large applications, involving a lot of functions and variables - currying will be helpful. 

3. The output of the code does not changes with currying. By fixing the parameters, we are only trying to

  avoid passing constant or redundant information every time with the function call. By using currying,
  the results of the code is not modified.