CSC/ECE 517 Fall 2010/ch1 1e bb: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(196 intermediate revisions by 2 users not shown)
Line 1: Line 1:
==Introduction==
This wiki page talks about the the features and advantages of mixing functional and object-oriented code. It is intended for people who have basic programming knowledge. The wiki page starts with the description and advantages of Functional and Object Oriented Programming [http://en.wikipedia.org/wiki/Programming_paradigm paradigms]. This is followed by a discussion of various approaches where both the paradigms can be combined in a piece of code. In the end, we describe about various programming languages which support both the paradigms.
==Functional Programming==
==Functional Programming==
Functional programming treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes on the application of functions, also called applicative programming.
Functional programming treats computation as the evaluation of mathematical functions.Programs are executed by evaluating expressions.It deals with immutable data,i.e, data that cannot be changed once created [http://en.wikipedia.org/wiki/Functional_programming 1 ].  
Functional programming decomposes a problem into a set of functions. Ideally, functions only take inputs and produce outputs, and don't have any internal state that affects the output produced for a given input. Well-known functional languages include the ML family (Standard ML, OCaml, and other variants) and Haskell.
In a functional program, input flows through a set of functions. Each function operates on its input and produces some output
A more practical benefit of functional programming is that it forces you to break apart your problem into small pieces. Small functions are also easier to read and to check for errors, thus debugging is easier.
Functional Programming discourages the use of variables.


*Functional programming decomposes a problem into a set of functions. Functions only take inputs and produce outputs, and don't maintain any internal state that affects the output produced for a given input.
*Functional programming breaks apart your problem into small pieces. Small functions are easy to read and to check for errors, thus debugging is easier.
*Functional Programming discourages the use of variables.
Pure Functional languages include the [http://en.wikipedia.org/wiki/ML_%28programming_language%29 ML family(Standard ML,OCaml)] and [http://en.wikipedia.org/wiki/Haskell_%28programming_language%29 Haskell].
An example of functional code in ML to calculate Factorial:


   fun factorial (0 : int) : int = 1
   fun factorial (0 : int) : int = 1
   | factorial (n : int) : int = n * factorial (n-1)
   | factorial (n : int) : int = n * factorial (n-1)


 
The above code snippet computes factorial of an integer recursively. In the first line, the fun factorial keyword defines a function. The notation '''''(0: int)''''' can be interpreted as ‘0 is of type int’ and ''''': int =1''''' means that the default return value is 1 when 0 is passed as an argument.
The above code snippet is a functional code written in ML to compute factorial of an integer recursively. In the first line, the fun factorial keyword defines a function. The notation '''''(0: int)''''' can be interpreted as ‘0 is of type int’ and ''''': int =1''''' means that the default return value is 1 when 0 is passed as an argument.


In the second line, '''''(n: int)''''' sets the argument n to integer. '''''int = n * factorial (n-1)''''' means the return value of recursive computation is an integer.
In the second line, '''''(n: int)''''' sets the argument n to integer. '''''int = n * factorial (n-1)''''' means the return value of recursive computation is an integer.


We can observe here that no additional variables are used here, no state information is maintained and there are no side-effects to any variables.
We can observe here that no additional variables are used here, no state information is maintained and there are no side-effects to any variables. The function just accepts an input, does some computation and returns the output.


==Object Oriented Programming==
==Object Oriented Programming==


Object-oriented programming (OOP) is a programming language model  that uses  objects which are discrete bundles of functions and procedures, often relating to a particular real-world concept such as a bank account holder or hockey player, together with they relate to each other.
Object-oriented programming (OOP) is a programming paradigm that treats program elements as objects that have data fields and functions that act on the data fields. Objects represent a real world concept like a person or fruit. These objects can interact with each other [http://en.wikipedia.org/wiki/Object-oriented_programming 5]
 
*Object Oriented Language decomposes a problem into a set of classes which specifies the state and behavior of real world objects
*The class variables maintain state information, while the methods provide functionality
*Multiple states can be maintained by defining multiple objects of the same class
*These objects interact with each other by passing messages
*Inheritance enables the classes to inherit state and behavior of a parent class
*Other powerful features of Object-Oriented Programming include data abstraction, encapsulation, modularity & polymorphism.
 
 
Object Oriented languages include [http://en.wikipedia.org/wiki/Java_%28programming_language%29 Java], [http://en.wikipedia.org/wiki/Python_%28programming_language%29 Python], [http://en.wikipedia.org/wiki/C%2B%2B C++], [http://en.wikipedia.org/wiki/Visual_Basic_.NET Visual Basic .NET] and Ruby.


Java, Python, C++, Visual Basic .NET and Ruby are the most popular OOP languages today.
 
An example of Object-Oriented code in JAVA to calculate Factorial:


   public class Factorial
   public class Factorial
Line 35: Line 54:
   }
   }


 
The method '''''public int factorial (int n)''''' computes the factorial of variable n. If the value of argument '''''n<=1''''' then 1 is returned. Otherwise, the statement '''''return n* factorial(n-1)''''' calls the function recursively.
The above code is written in JAVA to compute factorial of an integer. The method '''''public int factorial (int n)''''' computes the factorial of variable n. If the value of argument '''''n<=1''''' then 1 is returned. Otherwise, the statement '''''return n* factorial(n-1)''''' calls the function recursively.


A point to note here is that we can maintain various states of the variable private int fact in the above code. If we create 3 instances of the above class (f1, f2 and f3), then the below code in main can maintain 3 states of the variable private int fact.
A point to note here is that we can maintain various states of the variable private int fact in the above code. If we create 3 instances of the above class (f1, f2 and f3), then the below code in main can maintain 3 states of the variable private int fact.
Line 50: Line 68:
   }
   }


Thus object oriented approach can be used to maintain state information of a variable, which is completely opposite to the functional approach.


Thus an object oriented approach can be used to maintain state information of a variable, which is completely opposite to the functional approach.
==Mixing functional and object oriented code==


==Mixing functional and object oriented code==
Functional programming is a programming paradigm that uses the functions in their real mathematical sense. Functional programming provides powerful features which can be leveraged by a programmer to develop a clean & concise code. But at the same time, Object Oriented paradigm is crucial for designing the architecture of today's large industrial applications. A large enterprise software is based on object oriented approach because of better modularity in design, easier maintenance and easy extensibility.
 
Combining both these paradigms not only provide us a robust design structure, but also enable the programmers to develop solutions to complex problems quickly and effectively.


Functional programming is a programming paradigm that uses the functions in their real mathematical sense. Functional programming provides powerful features which can be leveraged by a programmer to develop a clean & concise code. Some of the basic features of Functional Programming are:
Some of the basic features of Functional Programming which can be combined with Object Oriented paradigm are:


*Lambda Calculus
*Lambda Calculus
*Immutability
*Currying
*Powerful pattern matching
*Powerful pattern matching
*Continuations


But at the same time, Object Oriented paradigm is crucial for programming current industrial applications. A large enterprise software is based on object oriented approach because of better modularity in design, easier maintenance and easy extensibility.
Because of individual features of both the programming approaches, many new programming languages enable the programmers to mix both object oriented and functional codes together. While the software design can be based on object oriented approach, its inner functionality can be supported using functional code.


Let us now understand how each of the above feature of Functional language fits in the Object Oriented paradigm.
====Using Lambda Calculus inside the Object Oriented code====
Lambda calculus is an integral part of functional programming. It is a formal system designed to investigate:
*function definition
*function application
*[http://en.wikipedia.org/wiki/Recursion recursion].
Lambda calculus can be used to define a computable function which maintains no state information. A Lambda function can be passed as an argument to other functions. This demonstrates an important functional fact that the lambda function behaves like a value [http://www.codingday.com/power-of-functional-programming-its-features-and-its-future/ 7]. This is a pure functional approach, but Lambdas can be embedded inside the object oriented code so as to make the code more clear, concise and state-less.


'''Using Lambda Calculus inside the object oriented code'''


Lambda calculus which is an integral part of functional programming, is a formal system designed to investigate function definition, function application and recursion. Lambda calculus can be used to define a computable function and can used to develop a formal set theory.
The below code in Ruby demonstrates the use of lambdas inside a Class:
A Lambda function can be passed as an argument to other functions. There is another concept called curried functions when using lambda functions in which, the function reduces the term and returns another function with the normal form.
The lambda calculus has only functions of one argument. In the curried function systems, a function with multiple arguments is expressed using a function whose result is another function. Every argument is reduced by default and returns a function.
This is a pure functional approach, but Lambdas can be embedded inside the object oriented code so as to make the code more clear, concise and state-less.


   class Array
   class Array
Line 80: Line 105:
   end
   end
   end
   end
   array = [1, 2, 3, 4]
   array = [1, 2, 3, 4]
   array.iterate!(lambda { |n| n ** 2 })
   array.iterate!(lambda { |n| n ** 2 })
   puts array.inspect
   puts array.inspect


 
The above code calculate the squares of the given numbers of an array. A class called '''''class Array''''' is defined which contains the method '''''iterate'''''. This is a pure object oriented approach.
 
The method '''''iterate''''' iterates through 1 to n. Inside the loop:
The above code is written in Ruby, to calculate the squares of the given numbers of an array. A class called class Array is defined which contains iterate method. This is a pure object oriented approach.
The method iterate iterates through 1 to n. Inside the loop:


   self[i] = code.call(n)
   self[i] = code.call(n)


calls the lambda construct for each array member for computing its square.
calls the '''''lambda''''' construct for each array member for computing its square.
The statement:
The statement:


Line 99: Line 121:
is a lambda construct with a single argument n. The value of n is squared using '''''n**2''''' and is returned back to the calling construct. This demonstrates a functional approach in the same code.
is a lambda construct with a single argument n. The value of n is squared using '''''n**2''''' and is returned back to the calling construct. This demonstrates a functional approach in the same code.
In the above program, we observe here that the basic functionality of squaring the number was implemented by a functional code, while the basic design of the program is still object-oriented.  Functional code can thus be used to fill up important gaps in the object oriented code and provides a way to implement the functionality in a more clear and concise manner.
In the above program, we observe here that the basic functionality of squaring the number was implemented by a functional code, while the basic design of the program is still object-oriented.  Functional code can thus be used to fill up important gaps in the object oriented code and provides a way to implement the functionality in a more clear and concise manner.
====Using Currying inside Object Oriented code====
There is another concept called curried functions in which a function reduces the terms and returns another function as a result. In the curried function systems, the result of a function with multiple arguments is expressed as another function.
Suppose there is a function which accepts 2 arguments. Using currying, this function is converted into a single argument function. It returns another function with a single argument, which in-turn returns the result.
Let us take a sample code to understand this concept:
'''Code without currying'''
  class add
  {
    //declare variables
    int num1, num2;
    //declare method
    def addnumbers(num1:Int, num2:Int) = num1 + num2
  }
  addnumbers(10, 20)  // output: 30
  addnumbers(30, 40)  // output: 70
We can observe that the above code snippet contains a class called add which contains 2 variables. There is a method called addnnumbers which accepts 2 arguments num1 and num2 and returns their sum. The same code is now written using currying -
'''Code with currying'''
  class add
  {
    //declare variables
    int num1, num2;
    //declare method
    def addnumbers(num1:Int) = (num2:Int) = num1 + num2
  }
  addnumbers(10, 20)  // output: 30
  addnumbers(30, 40)  // output: 70
The above code is written leveraging the concept of currying. We can observe that addnumbers function now accepts a single argument (num1:Int) and it returns the functional closure of the result, which in turn accepts (num2:Int) which finally computes the sum and returns it back.
We also note that strategy of calling such a function remains the same. The function '''''addnumbers''''' is called the same way by passing 2 arguments in both the cases.
====Pattern Matching in Object Oriented Code====
Functional languages provide a powerful capability of pattern matching. This feature can be leveraged inside an object oriented code to quickly match patterns and generate results. We take an example of a Ruby code where we demonstrate how easily, a user input can be compared with any pattern.
  class PatternMatch
    input=""
    def match()
    input = gets
    input = input =~ /Ruby/
    return input
    end
  end
The above Ruby code shows a class named '''''PatternMatch''''' which contains a variable '''''input''''' and a method '''''match'''''. The method '''''match''''' takes the user input and stores it in the variable '''''input'''''.
The statement:
  input = input =~ /Ruby/
compares the user input with the pattern "Ruby" and returns the starting position of the match. Suppose the user input was "I love Ruby", then the result would be 8.
==Programming Languages which support both Object Oriented and Functional code==
The solution to a problem can be obtained in an elegant & concise way if functional code supports Object oriented programming. Combining the features of both the approaches can lead to development of efficient and quick solutions of relatively complex problems. This realization has led to the support of functional paradigm in many Object Oriented Programming languages.
Languages like Scala, Clojure and Ruby support both Functional and Object Oriented approaches. Here is a description of some of the most famous “mixed” paradigm languages.


====Scala====
====Scala====


Scala is a general purpose programming language designed to express common programming patterns in a concise, elegant, and type-safe way. It smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application.
Scala is a general purpose programming language designed to express common programming patterns in a concise, elegant, and type-safe way. The name Scala stands for "scalable language", signifying that it is designed to grow depending on user demands. It integrates features of object-oriented and functional languages. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application[http://en.wikipedia.org/wiki/Scala_%28programming_language%29 10].  


Scala is object-oriented:
'''''Scala is object-oriented'''''
Scala is a pure object-oriented language in the sense that every value is an object. Types and behavior of objects are described by classes and traits. Classes are extended by subclassing and a flexible mixin-based composition mechanism as a clean replacement for multiple inheritance.
Scala is a pure object-oriented language in the sense that every value is an object. Types and behavior of objects are described by classes and traits. Classes are extended by subclassing.
 
'''''Scala is functional'''''


Scala is functional:
Scala is also a functional language in the sense that every function is a value. Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying. Scala's case classes and its built-in support for pattern matching model algebraic types used in many functional programming languages.
Scala is also a functional language in the sense that every function is a value. Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying. Scala's case classes and its built-in support for pattern matching model algebraic types used in many functional programming languages.
Lets take the same factorial example in Scala for a better understanding:


   object objfactorial extends Application {
   object objfactorial extends Application {
Line 118: Line 212:
   }
   }


The above Scala example has an '''''Application''''' class which can be used to quickly turn objects into executable programs.
'''''object''''' statement creates an object called '''''objfactorial''''' which extends the Application class. The Application class in Scala is used to convert objects to applications. This demonstrates the object oriented properties of Scala.
'''''def''''' statement is used to define a function '''''factorial''''' which takes an integer argument and its return type is integer. The statement:
  Int=  if (n == 0) 1 else n * factorial(n-1)


The '''''Application''''' class can be used to quickly turn objects into executable programs.
recursively calls the function '''''factorial''''' until the value of the passed parameter '''''n''''' becomes 0. It is computing the factorial of the given input and finally returning the result as an '''''Int'''''. This demonstrates the Functional properties of Scala.
'''''object''''' statement creates an object called '''''objfactorial'''''. This is Object Oriented code.
 
'''''def''''' statement is used to define a function '''''factorial''''' which takes an integer argument and its return type is integer. It is computing the factorial of the given input. This is functional code.
====Ruby====
 
Ruby is a dynamically typed Object Oriented Language which supports multiple programming paradigms, including functional, object oriented, imperative and reflective. In Ruby, everything is an object,every bit of information and code can have its own properties and actions. However, Ruby’s blocks can be functional. A Ruby programmer can attach a closure to any method, which generates a functional block inside an object oriented code.A closure is a piece of code that can access the lexical environment of its definition [http://www.ruby-lang.org/en/ 11].
 
Consider the following code snippet in Ruby which uses Object Oriented concepts like Classes and functional programming concepts like lambda.
 
class Multiply
  def initialize(n)
    @block = lambda {|a| n * a}
  end
  def mul(a)
    @block.call a
  end
end
twoMultiplier = Multiply.new 2                   
puts twoMultiplier.mul(6)
 
Here,'''''@block''''' is a closure. When we call the class ''Multiply'' using '''''twoAdder = Multiply.new 2''''' ,the ''initialize'' method is called by passing the parameter 2. Here n=2 binds itself to the block. So @block will be 2*a, that is,the closure remembers the parameter with which the initialize method was called even after the initialize method exits.
 
This value is used when the block is called in the add method. 
Thus,'''''twoMultiplier.mul(6)''''' will return 2*6 = 12


====Clojure====
====Clojure====


Clojure is a dynamic programming language that targets the Java Virtual Machine.It is designed to be a general-purpose language, combining the approachability and interactive development of a scripting language with an efficient and robust infrastructure for multithreaded programming. Clojure is a compiled language - it compiles directly to JVM bytecode, yet remains completely dynamic. Every feature supported by Clojure is supported at runtime. Clojure provides easy access to the Java frameworks, with optional type hints and type inference, to ensure that calls to Java can avoid reflection.
Clojure is designed as general purpose language.Clojure is a dynamic programming language that targets the Java Virtual Machine.Clojure is a functional language that explicitly supports programs as models and provides robust and easy-to-use facilities for managing identity and state in a single process in the face of concurrency [http://clojure.org/ 10].
 
Clojure’s model separates identity and state. It treats state as the value currently associated with the identity. Thus an identity can be in different states at different times, but the state itself doesn't change. That is, an identity has a state and that state is a true value, i.e. it never changes. If an identity appears to change, it is because it becomes associated with different state values over time.
 
In Clojure's model, value calculation is purely functional. Values never change. New values are functions of old, not mutations. But logical identity is well supported, via atomic references to values. The value of a reference (state of an identity) is always observable without coordination, and freely shareable between threads.
When programs are constructed this way, they are easier to understand and test as functional value calculation is independent of identity-value association.
 
Consider the following functional programming example in Clojure-
(defn make-adder [x]
  (let [y x]
    (fn [z] (+ y z))))
(def add2 (make-adder 2))
(add2 4)
 
Here,'''''defn make-adder [x]''''' defines a function called ''make-adder''.'''''let [y x]''''' gives a local name y for the value x.The scope of any local names is lexical, so a function created in the scope of local names will close over their values.'''''fn [z] (+ y z)''''' does the addition of y and z.
''
'''def add2 (make-adder 2)''''' calls the function ''make-adder'' passing the parameter 2 and calls this as ''add2''.Now, ''add2'' has computed 2+z. When '''''add2 4''''' is called it computes 2+4=6
 
 
The following program implements Run-Time Polymorphism which is an object-oriented programming concept.
(defmulti encounter (fn [x y] [(:Species x) (:Species y)]))
(defmethod encounter [:Bunny :Lion] [b l] :run-away)
(defmethod encounter [:Lion :Bunny] [l b] :eat)
(defmethod encounter [:Lion :Lion] [l1 l2] :fight)
(defmethod encounter [:Bunny :Bunny] [b1 b2] :mate)
(def b1 {:Species :Bunny :other :stuff})
(def b2 {:Species :Bunny :other :stuff})
(def l1 {:Species :Lion :other :stuff})
(def l2 {:Species :Lion :other :stuff})
(encounter b1 l1)
-> :run-away
(encounter l1 l2)
-> :fight
 
Here,'''''defmulti''''' is used to define multiple methods which have the same method name '''''encounter'''''.Depending on the parameters passed to the encounter method, one of the four methods is called.
'''''def''''' defines each of the different species.
When, '''''(encounter b1 l1)''''' is called, the first ''encounter'' method is called with the parameters ''Bunny'' and ''Lion''. As a result, ''run-away'' is printed.


==Conclusion==
==Conclusion==
Adding some functional programming capabilities within an object-oriented
language leads to benefits for object-oriented programming design. Functional Programming offers two facets with regard to functions:
*'''Purity''' means mathematical-like functions, without any possibilities of dealing with side-effects.this leads to nice properties, like simpler testing and ready-to-use parallelism.
*'''First-class citizenship''' means functions considered as any other values: this leads to better functional granularity design and specific programming techniques.
By mixing both functional and object-oriented code we can reap the advantages of both. It is widely being used in applications nowadays.


==References==
==References==
#[http://en.wikipedia.org/wiki/Functional_programming Wikipedia - Functional Programming]
#[http://www.cs.cornell.edu/riccardo/prog-smlnj/notes-011001.pdf Notes on programming Standard ML of New Jersey]
#[http://users.dickinson.edu/~braught/courses/cs132f01/classes/code/Factorial.src.html Introduction to Computing - Dickinson College]
#[http://en.wikipedia.org/wiki/Object-oriented_programming Wikipedia - Object Oriented Programming]
#[http://searchsoa.techtarget.com/sDefinition/0,,sid26_gci212681,00.html  More on Object Oriented Programming]
#[http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas Understanding Ruby Blocks, Procs and Lambdas - Robert Sosinski]
#[http://www.codingday.com/power-of-functional-programming-its-features-and-its-future/ Power of Functional Programming, its Features and its Future]
#[http://skillsmatter.com/podcast/open-source-dot-net/mike-wagg-mark-needham-functional-and-oo-approaches-to-c-sharp-programming Mixing Functional and Object Oriented Approaches to Programming in C#]
#[http://en.wikipedia.org/wiki/Programming_paradigm Programming Paradigm]
#[http://en.wikipedia.org/wiki/Recursion Recursion]
#[http://www.scala-lang.org/ Scala]
#[http://en.wikipedia.org/wiki/Scala_%28programming_language%29 Scala Wikipedia]
#[http://clojure.org/ Clojure]
#[http://www.ruby-lang.org/en/ Ruby]
#[http://en.wikipedia.org/wiki/Standard_ML Standard ML]
#[http://en.wikipedia.org/wiki/Haskell_%28programming_language%29 Haskell]
#[http://en.wikipedia.org/wiki/ML_%28programming_language%29 ML Family]
#[http://en.wikipedia.org/wiki/Java_%28programming_language%29 Java]
#[http://en.wikipedia.org/wiki/Python_%28programming_language%29 Python]
#[http://en.wikipedia.org/wiki/C%2B%2B C++ Programming Language]
#[http://en.wikipedia.org/wiki/Visual_Basic_.NET Visual Basic .Net]

Latest revision as of 23:56, 17 September 2010

Introduction

This wiki page talks about the the features and advantages of mixing functional and object-oriented code. It is intended for people who have basic programming knowledge. The wiki page starts with the description and advantages of Functional and Object Oriented Programming paradigms. This is followed by a discussion of various approaches where both the paradigms can be combined in a piece of code. In the end, we describe about various programming languages which support both the paradigms.

Functional Programming

Functional programming treats computation as the evaluation of mathematical functions.Programs are executed by evaluating expressions.It deals with immutable data,i.e, data that cannot be changed once created 1 .

  • Functional programming decomposes a problem into a set of functions. Functions only take inputs and produce outputs, and don't maintain any internal state that affects the output produced for a given input.
  • Functional programming breaks apart your problem into small pieces. Small functions are easy to read and to check for errors, thus debugging is easier.
  • Functional Programming discourages the use of variables.


Pure Functional languages include the ML family(Standard ML,OCaml) and Haskell.


An example of functional code in ML to calculate Factorial:

 fun factorial (0 : int) : int = 1
 | factorial (n : int) : int = n * factorial (n-1)

The above code snippet computes factorial of an integer recursively. In the first line, the fun factorial keyword defines a function. The notation (0: int) can be interpreted as ‘0 is of type int’ and : int =1 means that the default return value is 1 when 0 is passed as an argument.

In the second line, (n: int) sets the argument n to integer. int = n * factorial (n-1) means the return value of recursive computation is an integer.

We can observe here that no additional variables are used here, no state information is maintained and there are no side-effects to any variables. The function just accepts an input, does some computation and returns the output.

Object Oriented Programming

Object-oriented programming (OOP) is a programming paradigm that treats program elements as objects that have data fields and functions that act on the data fields. Objects represent a real world concept like a person or fruit. These objects can interact with each other 5

  • Object Oriented Language decomposes a problem into a set of classes which specifies the state and behavior of real world objects
  • The class variables maintain state information, while the methods provide functionality
  • Multiple states can be maintained by defining multiple objects of the same class
  • These objects interact with each other by passing messages
  • Inheritance enables the classes to inherit state and behavior of a parent class
  • Other powerful features of Object-Oriented Programming include data abstraction, encapsulation, modularity & polymorphism.


Object Oriented languages include Java, Python, C++, Visual Basic .NET and Ruby.


An example of Object-Oriented code in JAVA to calculate Factorial:

 public class Factorial
 {
   public int fact;
   public int factorial(int n)
   {
     if (n <= 1)  
       return 1;
     else 	      
      return n * factorial(n-1);
   }
 }

The method public int factorial (int n) computes the factorial of variable n. If the value of argument n<=1 then 1 is returned. Otherwise, the statement return n* factorial(n-1) calls the function recursively.

A point to note here is that we can maintain various states of the variable private int fact in the above code. If we create 3 instances of the above class (f1, f2 and f3), then the below code in main can maintain 3 states of the variable private int fact.

 public static void main(String argv[])
 {
   Factorial f1 = new Factorial();	//instance 1
   Factorial f2 = new Factorial();	//instance 2 
   Factorial f3 = new Factorial();	//instance 3
   f1.fact = f1.factorial(5);	//state 1 of int fact
   f2.fact = f2.factorial(9);	//state 2 of int fact
   f3.fact = f3.factorial(12);	//state 3 of int fact
 }

Thus object oriented approach can be used to maintain state information of a variable, which is completely opposite to the functional approach.

Mixing functional and object oriented code

Functional programming is a programming paradigm that uses the functions in their real mathematical sense. Functional programming provides powerful features which can be leveraged by a programmer to develop a clean & concise code. But at the same time, Object Oriented paradigm is crucial for designing the architecture of today's large industrial applications. A large enterprise software is based on object oriented approach because of better modularity in design, easier maintenance and easy extensibility.

Combining both these paradigms not only provide us a robust design structure, but also enable the programmers to develop solutions to complex problems quickly and effectively.

Some of the basic features of Functional Programming which can be combined with Object Oriented paradigm are:

  • Lambda Calculus
  • Currying
  • Powerful pattern matching


Let us now understand how each of the above feature of Functional language fits in the Object Oriented paradigm.

Using Lambda Calculus inside the Object Oriented code

Lambda calculus is an integral part of functional programming. It is a formal system designed to investigate:

  • function definition
  • function application
  • recursion.

Lambda calculus can be used to define a computable function which maintains no state information. A Lambda function can be passed as an argument to other functions. This demonstrates an important functional fact that the lambda function behaves like a value 7. This is a pure functional approach, but Lambdas can be embedded inside the object oriented code so as to make the code more clear, concise and state-less.


The below code in Ruby demonstrates the use of lambdas inside a Class:

 class Array
  def iterate!(code)
    self.each_with_index do |n, i|
      self[i] = code.call(n)
    end
  end
 end
 array = [1, 2, 3, 4]
 array.iterate!(lambda { |n| n ** 2 })
 puts array.inspect

The above code calculate the squares of the given numbers of an array. A class called class Array is defined which contains the method iterate. This is a pure object oriented approach. The method iterate iterates through 1 to n. Inside the loop:

 self[i] = code.call(n)

calls the lambda construct for each array member for computing its square. The statement:

 array.iterate!(lambda { |n| n ** 2 })

is a lambda construct with a single argument n. The value of n is squared using n**2 and is returned back to the calling construct. This demonstrates a functional approach in the same code. In the above program, we observe here that the basic functionality of squaring the number was implemented by a functional code, while the basic design of the program is still object-oriented. Functional code can thus be used to fill up important gaps in the object oriented code and provides a way to implement the functionality in a more clear and concise manner.

Using Currying inside Object Oriented code

There is another concept called curried functions in which a function reduces the terms and returns another function as a result. In the curried function systems, the result of a function with multiple arguments is expressed as another function.

Suppose there is a function which accepts 2 arguments. Using currying, this function is converted into a single argument function. It returns another function with a single argument, which in-turn returns the result.

Let us take a sample code to understand this concept:

Code without currying

 class add
 {
   //declare variables
   int num1, num2;
   //declare method
   def addnumbers(num1:Int, num2:Int) = num1 + num2
 }

 addnumbers(10, 20)   // output: 30
 addnumbers(30, 40)   // output: 70

We can observe that the above code snippet contains a class called add which contains 2 variables. There is a method called addnnumbers which accepts 2 arguments num1 and num2 and returns their sum. The same code is now written using currying -

Code with currying

 class add
 {
   //declare variables
   int num1, num2;
   //declare method
   def addnumbers(num1:Int) = (num2:Int) = num1 + num2
 }

 addnumbers(10, 20)   // output: 30
 addnumbers(30, 40)   // output: 70

The above code is written leveraging the concept of currying. We can observe that addnumbers function now accepts a single argument (num1:Int) and it returns the functional closure of the result, which in turn accepts (num2:Int) which finally computes the sum and returns it back.

We also note that strategy of calling such a function remains the same. The function addnumbers is called the same way by passing 2 arguments in both the cases.

Pattern Matching in Object Oriented Code

Functional languages provide a powerful capability of pattern matching. This feature can be leveraged inside an object oriented code to quickly match patterns and generate results. We take an example of a Ruby code where we demonstrate how easily, a user input can be compared with any pattern.

 class PatternMatch
   input=""
   def match()
    input = gets
    input = input =~ /Ruby/
    return input
   end
 end

The above Ruby code shows a class named PatternMatch which contains a variable input and a method match. The method match takes the user input and stores it in the variable input.

The statement:

 input = input =~ /Ruby/

compares the user input with the pattern "Ruby" and returns the starting position of the match. Suppose the user input was "I love Ruby", then the result would be 8.

Programming Languages which support both Object Oriented and Functional code

The solution to a problem can be obtained in an elegant & concise way if functional code supports Object oriented programming. Combining the features of both the approaches can lead to development of efficient and quick solutions of relatively complex problems. This realization has led to the support of functional paradigm in many Object Oriented Programming languages.

Languages like Scala, Clojure and Ruby support both Functional and Object Oriented approaches. Here is a description of some of the most famous “mixed” paradigm languages.

Scala

Scala is a general purpose programming language designed to express common programming patterns in a concise, elegant, and type-safe way. The name Scala stands for "scalable language", signifying that it is designed to grow depending on user demands. It integrates features of object-oriented and functional languages. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application10.

Scala is object-oriented

Scala is a pure object-oriented language in the sense that every value is an object. Types and behavior of objects are described by classes and traits. Classes are extended by subclassing.

Scala is functional

Scala is also a functional language in the sense that every function is a value. Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying. Scala's case classes and its built-in support for pattern matching model algebraic types used in many functional programming languages.


Lets take the same factorial example in Scala for a better understanding:

 object objfactorial extends Application {
   def factorial(n: Int): Int =
     if (n == 0) 1 else n * factorial(n-1)
   val f3 = factorial(3); val f4 = factorial(4)
   println("3! = " + f3)
   println("4! = " + f4)
 }

The above Scala example has an Application class which can be used to quickly turn objects into executable programs. object statement creates an object called objfactorial which extends the Application class. The Application class in Scala is used to convert objects to applications. This demonstrates the object oriented properties of Scala. def statement is used to define a function factorial which takes an integer argument and its return type is integer. The statement:

 Int=  if (n == 0) 1 else n * factorial(n-1)

recursively calls the function factorial until the value of the passed parameter n becomes 0. It is computing the factorial of the given input and finally returning the result as an Int. This demonstrates the Functional properties of Scala.

Ruby

Ruby is a dynamically typed Object Oriented Language which supports multiple programming paradigms, including functional, object oriented, imperative and reflective. In Ruby, everything is an object,every bit of information and code can have its own properties and actions. However, Ruby’s blocks can be functional. A Ruby programmer can attach a closure to any method, which generates a functional block inside an object oriented code.A closure is a piece of code that can access the lexical environment of its definition 11.

Consider the following code snippet in Ruby which uses Object Oriented concepts like Classes and functional programming concepts like lambda.

class Multiply
  def initialize(n)
    @block = lambda {|a| n * a}
  end
  def mul(a)
    @block.call a
  end
end
twoMultiplier = Multiply.new 2                     
puts twoMultiplier.mul(6)

Here,@block is a closure. When we call the class Multiply using twoAdder = Multiply.new 2 ,the initialize method is called by passing the parameter 2. Here n=2 binds itself to the block. So @block will be 2*a, that is,the closure remembers the parameter with which the initialize method was called even after the initialize method exits.

This value is used when the block is called in the add method. Thus,twoMultiplier.mul(6) will return 2*6 = 12

Clojure

Clojure is designed as general purpose language.Clojure is a dynamic programming language that targets the Java Virtual Machine.Clojure is a functional language that explicitly supports programs as models and provides robust and easy-to-use facilities for managing identity and state in a single process in the face of concurrency 10.

Clojure’s model separates identity and state. It treats state as the value currently associated with the identity. Thus an identity can be in different states at different times, but the state itself doesn't change. That is, an identity has a state and that state is a true value, i.e. it never changes. If an identity appears to change, it is because it becomes associated with different state values over time.

In Clojure's model, value calculation is purely functional. Values never change. New values are functions of old, not mutations. But logical identity is well supported, via atomic references to values. The value of a reference (state of an identity) is always observable without coordination, and freely shareable between threads. When programs are constructed this way, they are easier to understand and test as functional value calculation is independent of identity-value association.

Consider the following functional programming example in Clojure-

(defn make-adder [x]
  (let [y x]
    (fn [z] (+ y z))))
(def add2 (make-adder 2))
(add2 4)

Here,defn make-adder [x] defines a function called make-adder.let [y x] gives a local name y for the value x.The scope of any local names is lexical, so a function created in the scope of local names will close over their values.fn [z] (+ y z) does the addition of y and z. def add2 (make-adder 2) calls the function make-adder passing the parameter 2 and calls this as add2.Now, add2 has computed 2+z. When add2 4 is called it computes 2+4=6


The following program implements Run-Time Polymorphism which is an object-oriented programming concept.

(defmulti encounter (fn [x y] [(:Species x) (:Species y)]))
(defmethod encounter [:Bunny :Lion] [b l] :run-away)
(defmethod encounter [:Lion :Bunny] [l b] :eat)
(defmethod encounter [:Lion :Lion] [l1 l2] :fight)
(defmethod encounter [:Bunny :Bunny] [b1 b2] :mate)
(def b1 {:Species :Bunny :other :stuff})
(def b2 {:Species :Bunny :other :stuff})
(def l1 {:Species :Lion :other :stuff})
(def l2 {:Species :Lion :other :stuff})

(encounter b1 l1)
-> :run-away
(encounter l1 l2)
-> :fight

Here,defmulti is used to define multiple methods which have the same method name encounter.Depending on the parameters passed to the encounter method, one of the four methods is called. def defines each of the different species. When, (encounter b1 l1) is called, the first encounter method is called with the parameters Bunny and Lion. As a result, run-away is printed.

Conclusion

Adding some functional programming capabilities within an object-oriented language leads to benefits for object-oriented programming design. Functional Programming offers two facets with regard to functions:

  • Purity means mathematical-like functions, without any possibilities of dealing with side-effects.this leads to nice properties, like simpler testing and ready-to-use parallelism.
  • First-class citizenship means functions considered as any other values: this leads to better functional granularity design and specific programming techniques.

By mixing both functional and object-oriented code we can reap the advantages of both. It is widely being used in applications nowadays.

References

  1. Wikipedia - Functional Programming
  2. Notes on programming Standard ML of New Jersey
  3. Introduction to Computing - Dickinson College
  4. Wikipedia - Object Oriented Programming
  5. More on Object Oriented Programming
  6. Understanding Ruby Blocks, Procs and Lambdas - Robert Sosinski
  7. Power of Functional Programming, its Features and its Future
  8. Mixing Functional and Object Oriented Approaches to Programming in C#
  9. Programming Paradigm
  10. Recursion
  11. Scala
  12. Scala Wikipedia
  13. Clojure
  14. Ruby
  15. Standard ML
  16. Haskell
  17. ML Family
  18. Java
  19. Python
  20. C++ Programming Language
  21. Visual Basic .Net