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

From Expertiza_Wiki
Jump to navigation Jump to search
mNo edit summary
 
(42 intermediate revisions by the same user not shown)
Line 1: Line 1:
'''
'''
== Currying ==
== What is Currying ==
'''
'''


[http://en.wikipedia.org/wiki/Currying Currying] is a transformational technique in [http://en.wikipedia.org/wiki/Functional_programming functional programming]. It helps us to reduce the number of dangling arguments that are passed to a function, if we have some prior knowledge of the usage of that function. It helps to write code which is productive and elegant, though there is hardly any instance when currying is absolutely required. [http://en.wikipedia.org/wiki/Christopher_Strachey Christopher Strachey] had coined the term "currying" in 1967 in reference to logician [http://en.wikipedia.org/wiki/Haskell_Curry Haskell Curry]. 


Currying is a technique in functional programming. It is based on a very simple mathematical concept that:
In ordinary words, currying says that”if we fix some arguments of a function, we 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. Thus we have reduced the number of arguments in the function on the cost of making it a more specific one.


Languages like [http://en.wikipedia.org/wiki/ML_%28programming_language%29 ML], [http://en.wikipedia.org/wiki/Haskell_%28programming_language%29 Haskell] and [http://en.wikipedia.org/wiki/Ruby_%28programming_language%29 Ruby] support currying by providing built in support. These languages have functionalities which allow certain multi-argument functions getting expanded to their curried form. In general, languages that support [http://en.wikipedia.org/wiki/Closure_%28computer_science%29 closures] can be used to write curried functions.
'''
== The Mathematical Concept of Currying ==
'''
The concept of currying has been borrowed from mathematics. A mathematical concept says that all the below functions are equivalent.
<code><pre>
lambda { |a, b, c| ... }
lambda { |a, b, c| ... }
lambda { |a| lambda { |b| lambda { |c| ... } } }
lambda { |a| lambda { |b| lambda { |c| ... } } } or
or
lambda { |a| lambda { |b, c| ... } }
lambda { |a| lambda { |b, c| ... } }
</pre></code>


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 and so on. 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| zoog( 1, 2, c ) }
Two arguments curried in, one argument still dangling.


Two arguments curried in, one argument still dangling.
'''
== Illustrations ==
'''


'''Example 1'''
Currying in Ruby is pretty straight forward. Typically we use the [http://en.wikipedia.org/wiki/Lambda_calculus 'lambda'] method to curry the basic function to create new functions.
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)
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 site and player is – Mp3 Site and Jukebox Player. Instead of passing the player name
every time to the site, we can curry the player name in the function play. In this way, we’ll be
sending only the minimum necessary parameters required to play the file while the site-specific
information, i.e. the player name will be curried.
<code><pre>
def play(albumname,songname,player)
       @albumname = albumname
       @albumname = albumname
       @Trackname = songname
       @Trackname = songname
Line 30: Line 54:
   end
   end


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


Input Without Using Currying
#Input Without Using Currying, three parameters need to be passed everytime
play("The Best of Bryan Adams", "Track 7", "Jukebox")
play("MLTR", "Track 1"," Jukebox ")
play("The Best of Bryan Adams", "Track 7", "Jukebox")
play("MLTR", "Track 1"," Jukebox ")
play("MLTR", "Track 11"," Jukebox ")


Input Using Currying
#Input Using Currying, two parameters are passed everytime
mp3site.call("The Best of Bryan Adams", "Track 7")
mp3site.call("MLTR", "Track 1")
mp3site.call("The Best of Bryan Adams", "Track 7")
mp3site.call("MLTR", "Track 1")
mp3site.call("MLTR", "Track 11")


</pre></code>
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 as per our assumption about the relevant information.


'''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  
=== Example 2 ===
def calculate(var1,op,var2)     
'''
  if op == '+'
The following program illustrates the concept of Currying using a simple example of a basic calculator.
    return puts "The Result of addition is      : #{var1+var2}"
The method calculator accepts two operands var1 & var2 performs the operation specified by 'op' on the
  elsif op == '-'
two operands and returns the result.
    return puts "The Result of subtraction is  : #{var1-var2}"
The method 'calculate' thus accepts 3 arguments. Now, calling this method again and again would lead to
  elsif op == '*'
poor readability. Instead by implementing currying we can improve the readability of the code.
    return puts "The Result of multiplication is: #{var1*var2}"
In the following code we have made use of the 'calculate' method with currying as well as without using
  elsif op == '/'
curring. Places where 'calculate' is called using calculate(3,+,4) are instances where currying is not
    return puts "The Result of division is      : #{var1/var2}"
used. Places where either of 'add','sub','mul','div' have been used implements currying.
  else
<code><pre>
    return puts "wrong choice ! "
 
  end
#definition of 'calculate' method
end  
 
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  
#Following 'calculate' method calls are without using currying  
   calculate(3,'+',4)
   calculate(3,'+',4)
   calculate(4,'-',5)
   calculate(4,'-',5)
Line 68: Line 112:
   calculate(4,'/',2)
   calculate(4,'/',2)
   
   
Currying Implementation using 'lambda'  
#Currying Implementation using 'lambda'  
   add = lambda {|x , y| calculate(x,'+',y)}
   add = lambda {|x , y| calculate(x,'+',y)}
   sub = lambda {|x , y| calculate(x,'-',y)}
   sub = lambda {|x , y| calculate(x,'-',y)}
Line 74: Line 119:
   div = lambda {|x , y| calculate(x,'/',y)}  
   div = lambda {|x , y| calculate(x,'/',y)}  


Following method calls are by using currying  
#Following method calls are by using currying  
   add.call(3,4)
   add.call(3,4)
   sub.call(4,5)
   sub.call(4,5)
   mul.call(4,2)
   mul.call(4,2)
   div.call(4,2)
   div.call(4,2)
</pre></code>
'''
== 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.
   
   
'''Features of Currying'''
2. The reliability of the code, which is very essential for the reliability of the 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.


1.The above example illustrates that currying helps improve readability of code and therefore its maintainability.
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,
2. Results without currying and with currying are same.  
the result of the code is not modified.
 
'''
 
== References ==
'''
1. [http://en.wikipedia.org/wiki/Currying More On Currying]
 
2. [http://moonbase.rydia.net/mental/blog/programming/currying-in-ruby More about Currying in Ruby and Lambda function]
 
3. [http://www.groupsrv.com/computers/post-2438696.html Discussion on Usefulness of Currying]
 
4. [http://slesinsky.org/brian/code/guice_with_curry.html Example of Currying]
 
'''
== External Links ==
'''
 
1. [http://www.ruby-lang.org/en/ Ruby language home page]
 
2. [http://kzk9.net/software/miscprograms/ruby/ Programs in Ruby]


3.Also the reliability if the code increases since we are reducing the number of parameters to be passed, i.e. the user is less prone to make mistakes in using the method.
3. [http://ruby.about.com/od/learnruby/Learn_to_Program_with_Ruby.htm Learn to Program with Ruby]

Latest revision as of 00:29, 20 September 2007

What is Currying

Currying is a transformational technique in functional programming. It helps us to reduce the number of dangling arguments that are passed to a function, if we have some prior knowledge of the usage of that function. It helps to write code which is productive and elegant, though there is hardly any instance when currying is absolutely required. Christopher Strachey had coined the term "currying" in 1967 in reference to logician Haskell Curry.

In ordinary words, currying says that”if we fix some arguments of a function, we 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. Thus we have reduced the number of arguments in the function on the cost of making it a more specific one.

Languages like ML, Haskell and Ruby support currying by providing built in support. These languages have functionalities which allow certain multi-argument functions getting expanded to their curried form. In general, languages that support closures can be used to write curried functions.

The Mathematical Concept of Currying

The concept of currying has been borrowed from mathematics. A mathematical concept says that all the below functions are equivalent.

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 and so on. 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.

Illustrations

Currying in Ruby is pretty straight forward. Typically we 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 site and player is – Mp3 Site and Jukebox Player. Instead of passing the player name every time to the site, we can curry the player name in the function play. In this way, we’ll be sending only the 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 Currying
 
 mp3site = lambda{|albumname,songname| play(albumname,songname,"Jukebox")}

#Input Without Using Currying, three parameters need to be passed everytime
 
 play("The Best of Bryan Adams", "Track 7", "Jukebox")
 play("MLTR", "Track 1"," Jukebox ")
 play("MLTR", "Track 11"," Jukebox ")

#Input Using Currying, two parameters are passed everytime
 
 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 as per our assumption about the relevant information.

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 readability. 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 the 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 result of the code is not modified.

References

1. More On Currying

2. More about Currying in Ruby and Lambda function

3. Discussion on Usefulness of Currying

4. Example of Currying

External Links

1. Ruby language home page

2. Programs in Ruby

3. Learn to Program with Ruby