CSC/ECE 517 Fall 2012/ch1 1w8 aa: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(24 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= Introduction =
= Introduction =
This wiki page explores the idea of mixing functional and object-oriented code. Mixing different [http://en.wikipedia.org/wiki/Multi-paradigm#Multi-paradigm_programming_language programming paradigms] is called multi-paradigm programming. There are four major paradigms:
* [http://en.wikipedia.org/wiki/Imperative_paradigm Procedural/imperative paradigms]: Assembly, C, C++, Java, C#
* Object Oriented paradigm : C++, Java, Python, Ruby, Scala, C#
* Functional Paradigm : Lisp, Haskell, Clojure, Scala, OCaml, Ruby
* [http://en.wikipedia.org/wiki/Logic_programming Logic Paradigm]: Prolog
In this wiki we explain how functional and object-oriented paradigms can be mixed. First, we explain what functional and object-oriented style programming is. Secondly, we will show how to apply functional techniques to object-oriented programming. Lastly, we discuss languages that support mixing functional and object-oriented code.


= Functional Programming =
= Functional Programming =


Functional programming treats computation as the evaluation of mathematical functions. It is compute-centric rather than data-centric. Functional programming keeps no global state, does not use for or while loops, and data is immutable****. Instead, everything is done using functions, usually functions that evaluate mathematical expressions. Each of these functions maintain no internal state and will always produce the same output given the same input.  
Functional programming treats computation as the evaluation of mathematical functions. It is compute-centric rather than data-centric. Functional programming keeps no global state, does not use for or while loops, and mandates that data is [http://en.wikipedia.org/wiki/Immutable immutable]. Instead, everything is done using functions, usually functions that evaluate mathematical expressions. Each of these functions maintain no internal state and will always produce the same output given the same input.  
 
== Example Contrasting Imperitive and Functional Styles ==


Let's look at an example. Suppose we have a list of numbers and we want to multiply each number in the list by 2. The first approach is the imperitive style:
Let's look at an example. Suppose we have a list of numbers and we want to multiply each number in the list by 2. The first approach is the imperitive style:
Line 24: Line 34:
   
   
Notice that there is no global data nor any nested loops and the bound checking is handled internally within the map function. The programmer is relieved of of runtime errors and thus can debug the program easily.  
Notice that there is no global data nor any nested loops and the bound checking is handled internally within the map function. The programmer is relieved of of runtime errors and thus can debug the program easily.  
== Advantages of Functional Programming ==


Some advantages of this approach are:
Some advantages of this approach are:
Line 37: Line 49:
We could code in object-oriented paradigm as:
We could code in object-oriented paradigm as:


   class Limbs  /*define a class of limbs*/
   class Limbs   
  #define a class of limbs
     def initialize(limbs,length,colorofskin)
     def initialize(limbs,length,colorofskin)
     @limbs=limbs
     @limbs=limbs
Line 44: Line 57:
     end
     end
   end
   end
   limbs=Limbs.new("legs","100cm","white")  /*create a new object in class "Limbs"*/
   limbs=Limbs.new("legs","100cm","white")   
   class Legs<Limbs  /*create a subclass "Legs",which belong to class"Limbs"*/
  #create a new object in class "Limbs"
   class Legs<Limbs   
  #create a subclass "Legs",which belong to class"Limbs"
     def initialize(legs,length,colorofskin)
     def initialize(legs,length,colorofskin)
       super(length,colorofskin)
       super(length,colorofskin)
Line 51: Line 66:
     end  
     end  
   end
   end
   legs=legs.new("left leg") /*create a new object in class of "Legs"*/
   legs=legs.new("left leg")  
  #create a new object in class of "Legs"


== Features of Object-oriented Programming ==
== Features of Object-oriented Programming ==
Line 68: Line 84:
= Mixing Functional and Object-Oriented Programming =
= Mixing Functional and Object-Oriented Programming =


Motivation for Mixing
In object-oriented world, data and operations are grouped together into modular units called objects and we combine objects into structured networks to form a program. The results are depend on arguments and objects' state at method invocation time. While in functional world, the basic elements are variables in the mathematical sense and functions in the mathematical sense. Functional programming can reduce side-effects. If there is no side-effects, it means your can apply the function at anywhere freely. No matter how you apply this function, the same input arguments produce the same results.
 
{| class="wikitable" border="2"
|-
!  Functional - Mathematical Functions
!  Object-Oriented - Objects
|-
| Compact
| Modular
|-
| Easy to debug
| Easy to maintain
|-
|}
 
Overall, object-oriented programming requires more upfront design, but is easier to maintain long-term. Obviously if we apply functional programming techniques to object-oriented programming, everything can be done better--the code is easier to write, runs faster, and uses less memory.


== Functional Techniques useful for Object-Oriented Programming ==
== Functional Techniques useful for Object-Oriented Programming ==
In object-oriented world, data and operations are grouped together into modular units called objects and we combine objects into structured networks to form a program. The results are depend on arguments and objects' state at method invocation time. While in functional world, the basic elements are variables in the mathematical sense and functions in the mathematical sense. Functional programming can reduce side-effects. If there is no side-effects, it means your can apply the function at anywhere freely. No matter how you apply this function, the same input arguments produce the same results.


According to above-mentioned information, we can perform functional programming on an object-oriented programming language because:
According to above-mentioned information, we can perform functional programming on an object-oriented programming language because:
Line 115: Line 145:


=== Currying ===
=== Currying ===
In the above information we have learned much about lambda calculus, which take care of one argument, now let me introduce you another concept called currying functions which takes in multiple arguments and returns a chain of functions with lesser number of arguments. It can be interpreted as the technique to decompose a function that takes n parameters into n functions and each of the n functions takes one parameter.
Currying is really an interesting concept. Let's take a sample code in JavaScript to understand it:
  //This is a function for calculating x+y. The difference between this function and general is that this is a currying function.
  function add(x, y)
  {
  if(x!=null && y!=null) return x + y;
  else if(x!=null && y==null) return function(y)
  {
    return x + y;  //return a closure with parameter y for subsequent calculations
    }
  else if(x==null && y!=null) return function(x)
  {
    return x + y;  //return a closure with parameter x for subsequent calculations
    }
  }
  var a = add(3, 4);  //compute the value of (3+4) and return the value of 7
  var b = add(2);  //add(2) is equal to a function of (2+y)
  var c = b(10);  //pass 10 to y, and return the value of (2+10) which is 12
In the above sample, b=add(2) gives us a currying function of add(), which is function of y when x=2.
More interestingly, we can define a currying form of arbitrary functions.
  function Foo(x, y, z, w)
  {
  var args = arguments;
  if(Foo.length < args.length)
    return function()
    {
      return args.callee.apply(Array.apply([], args).concat(Array.apply([], arguments)));
    }
  else
    return x + y – z * w;
  }


=== Pattern Matching ===
=== Pattern Matching ===
What is pattern matching? I think all of you do know what it is, you just don't know you know it. The semantics are equally straightforward.Firstly, we evaluate the value expression, then we walk down the clauses. For each one, we see if the pattern matches the value. If so, we execute the body and end. Simply put, pattern matching is a technique to search string for the occurrence of any patterns or regularity.


== Examples of Mixing ==
Pattern matching allows you to do different calculations according to different identifier values. It looks the same with nests of "if...else" statements, as well as "switch" statements in C++ and C#. But here it is much stronger and more flexible.
 
You may find that there are two main types of usage of pattern matching:
* To search and find a particular value.
* To find a particular value and replace it with selected text.
 
For example, the following code snippets writes a message if a string contains the text Perl or Python:
 
  if line =~ /Perl|Python/
  puts "Scripting language mentioned:#{line}"  
  end


A number of programming languages support mixing of both functional and object-oriented code. Three of these (Scala, Ruby, and Conjure), are described in more detail below.
Next, let us consider the following sample in which a part of a string matched by a regular expression can be replaced with different text using one of Ruby’s substitution methods:


=== Scala ===
  line.sub(/Perl/, 'Ruby') # replace first 'Perl' with 'Ruby'
  line.gsub(/Python/, 'Ruby') # replace every 'Python' with 'Ruby'


[http://www.scala-lang.org/ Scala] is a modern multi-paradigm 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. [http://www.scala-lang.org/ Scala] was conceived in 2001 and implemented by Martin Odersky. It has a number of features.
Advantages of Pattern Matching:
* It allows concise, readable deconstruction of complex data structures.
* It gives a possible separation of data structure and respective functionality.


==== Statically Typed ====
== Examples of Mixing ==
[http://www.scala-lang.org/ Scala] belongs to the family of languages which encode the type information of each and every variable in the generated code. The compiler makes sure you are not doing something incorrectly. For example, lets consider the following example of code where the type is not encoded,


In [http://www.ruby-lang.org/en/ Ruby],
A number of programming languages support mixing of both functional and object-oriented code. Three of these (Scala, Ruby, and Conjure), are described in more detail below.
  irb(main):001:0> str="Hello World"
    => "Hello World"
    irb(main):002:0> puts str.class
    String
    irb(main):003:0> str=123
    => 123
    irb(main):004:0> puts str.class
    Fixnum


In the above example, first we define 'str' variable to be of type String and then as a number. So basically, no type information is associated with the variable at any point in the program. Hence we can easily reassociate that variable with an object/instance
=== Scala ===
of a different type. This is a feature of all dynamically typed languages(like Ruby, Python, Clojure). However most of the statically typed languages such as Scala, Java, C/C++ do not allow you do so. In [http://www.scala-lang.org/ Scala],


  scala> var str="Hello World"
[http://www.scala-lang.org/ Scala] is a modern multi-paradigm 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. [http://www.scala-lang.org/ Scala] was conceived in 2001 and implemented by Martin Odersky. It supports mixing functional and object-oriented code.
  str: java.lang.String = Hello World
  scala> str=123
  <console>:6: error: type mismatch;
  found  : Int(123)
  required: java.lang.String
        str=123


==== Mixed paradigm ====
==== Mixing Functional and Object-Oriented Code in Scala ====
[http://www.scala-lang.org/ Scala] is a strange specimen. It is a complete blend of object oriented and functional programming. How can this happen? Functional world advocates immutability but object oriented world is all about state and how do you mutate it to fit your needs. [http://www.scala-lang.org/ Scala] allows you create both mutable and immutable objects. Consider the following example,
[http://www.scala-lang.org/ Scala] is a strange specimen. It is a complete blend of object-oriented and functional programming. How can this happen? The functional world advocates immutability, but the object-oriented world focuses on the state and how to change it to fit your needs. [http://www.scala-lang.org/ Scala] allows you create both mutable and immutable objects. Consider the following example,
  val str: String = "Hello World"
  val str: String = "Hello World"
In the first line, an immutable version(a misnomer indeed) of <code>str</code> is being created . Roughly translating the above line to Java is below:
In the first line, an immutable version(a misnomer indeed) of <code>str</code> is being created . A rough translation into Java is below:


  final String str = "Hello World"; //note the extra semi-colon
  final String str = "Hello World"; //note the extra semi-colon
Line 159: Line 222:
  val list: List[String] = List("Scala", "is", "the coolest", "language", "in the world!")
  val list: List[String] = List("Scala", "is", "the coolest", "language", "in the world!")


The same code can be written in Java as below
The same code can be written in Java as:


   List<String> mutableList = new ArrayList<String>();
   List<String> mutableList = new ArrayList<String>();
Line 169: Line 232:
   List<String> immutableList = Collections.immutableList(mutableList);
   List<String> immutableList = Collections.immutableList(mutableList);


Compared to Java, [http://www.scala-lang.org/ Scala] reduces the total number of lines you need to type and at the same time looks so much simpler and less verbose. Even though the above example shows immutable collection example, scala also provides mutable collection and object types under the package <code>scala.collection.mutable.*</code>
Compared to Java, [http://www.scala-lang.org/ Scala] reduces the total number of lines you need to type and at the same time looks much simpler and less verbose. Even though the above example shows an immutable collection, scala also provides mutable collections and object types in the package <code>scala.collection.mutable.*</code>


As it can be observed, even though [http://www.scala-lang.org/ Scala] advocates immutability, it does not restrict you from creating mutable objects. So its the best of both worlds. Another part of functional world is the concept of functions as ''''first class members'''' of the language. Some of the common languages like Ruby, Python and JavaScript all incorporate this feature. In the sense you can pass around functions to methods as a parameter. Enough talking;
As can be observed, even though [http://www.scala-lang.org/ Scala] advocates immutability, it does not restrict you from creating mutable objects. So it's the best of both worlds. Another part of the functional world is the concept of functions as ''''first class members'''' of the language. Some of the common languages like Ruby, Python and JavaScript all incorporate this feature. In the sense you can pass around functions to methods as a parameter. Enough talking;


Let us have a class say <code>'Person'</code> which has properties, <code>name</code> and another variable <code>age</code>.
Let us have a class say <code>'Person'</code> which has properties, <code>name</code> and another variable <code>age</code>.
Line 216: Line 279:
In fact, every function is an object in [http://www.scala-lang.org/ Scala]. Scala's standard library has a number of functions which are objects themselves.
In fact, every function is an object in [http://www.scala-lang.org/ Scala]. Scala's standard library has a number of functions which are objects themselves.


==== Sophisticated Syntax/Features ====
==== Implicits in Scala ====
Sophisticated syntax and features are present in other functional languages like Haskell, (O)Caml and Erlang. Consider the following example,
 
  val name = "Jackie Chan"
  println(name.getClass) //prints out String.
 
Previously we saw that [http://www.scala-lang.org/ Scala] is a statically typed language and yet in the above example we don't specify what type <code>name</code> is. In Java, you would type in the following:
 
String name = "Jackie Chan"
 
In Java you specify what type the name variable is, but the [http://www.scala-lang.org/ scala] compiler can automatically detect the type of the variable even if you don't specify it. Consider the following example,
 
case class Person(name: String, age: Int)
val persons = List(
                        Person("Jackie Chan", 51), Person("Jet Li", 41),
                        Person("RajniKanth", 51), Person("Kamal Hasan", 44),
                        Person("Martin Odersky", 18), Person("Steve Yegge", 23))
//notice that you don't have to use 'new' keyword to create new instances. This is taken care of by the companion objects.
 
The above lines of code create a list with 6 different persons(An immutable list)
 
Now, just like ruby, scala supports the concepts of [http://en.wikipedia.org/wiki/Closure_(computer_science) closure]. Let's see what it is.
 
val twentyThree: List[Person] = persons.filter( { p: Person => p.age == 3})
 
In the above set of lines, the code within the '{ }' brackets is a function's body. The compiler created a function which takes a single argument and returns either true or false.
 
==== A Scalable Language ====
In almost all programming languages, there is a necessity to profile the running time of the procedures and tune its performance. The old way of doing things in Java would be:
In almost all programming languages, there is a necessity to profile the running time of the procedures and tune its performance. The old way of doing things in Java would be:


Line 284: Line 320:
That's not right! The function <code>timeIt</code> looks like a feature built into the language. Try saving the above code into a separate file and run it - It will still work. Using this feature, it is possible to build powerful DSL languages which can run at full speed on JVM.
That's not right! The function <code>timeIt</code> looks like a feature built into the language. Try saving the above code into a separate file and run it - It will still work. Using this feature, it is possible to build powerful DSL languages which can run at full speed on JVM.


Ruby allows you to add new methods to objects. This feature is often called as [http://en.wikipedia.org/wiki/Monkey_patch Monkey Patching] because you are splitting open the class and adding/overriding methods (in)|(to) the class. Often this leads to unexpected behavior at runtime because, other libraries including into build path may depend on some methods which you changed. Scala provides yet another feature called implicits.
Ruby allows you to add new methods to objects. Since you are splitting open the class and adding/overriding methods (in)|(to) the class, this feature is often called [http://en.wikipedia.org/wiki/Monkey_patch Monkey Patching]. Because other libraries may depend on some methods which you changed, often this leads to unexpected behavior at runtime. However, Scala provides yet another feature called [http://en.wikipedia.org/wiki/Implicit_function implicits] which helps you do this better.


In Java, <code>String</code> class is <code>final</code> so there is no way you can add new methods to it. But with implicits you can do more! Suppose you have some text in memory and you know it represents a number. But in Java the usual way to convert string to int is to do a <code>Integer.parseInt(string)</code> which seems so unnecessary. Let us make our lives easier...
In Java, <code>String</code> class is <code>final</code> so there is no way you can add new methods to it. But with implicits you can do more! Suppose you have some text in memory and you know it represents a number. But in Java the usual way to convert string to int is to do a <code>Integer.parseInt(string)</code> which seems so unnecessary. Let us make our lives easier...
Line 301: Line 337:


Ruby is another language that, like Scala, supports mixing functional and object-oriented code. It 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].
Ruby is another language that, like Scala, supports mixing functional and object-oriented code. It 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].
==== Ruby Mixing Example ====


Consider the following code snippet in Ruby which uses Object Oriented concepts like Classes and functional programming concepts like lambda.
Consider the following code snippet in Ruby which uses Object Oriented concepts like Classes and functional programming concepts like lambda.
Line 319: Line 357:
This value is used when the block is called in the add method.   
This value is used when the block is called in the add method.   
Thus,'''''twoMultiplier.mul(6)''''' will return 2*6 = 12
Thus,'''''twoMultiplier.mul(6)''''' will return 2*6 = 12
==== Functional Style Coding in Ruby Blocks ====


Blocks are basically nameless functions which can be passed to a function and then that function can invoke the passed in nameless function. This is a common style called [http://en.wikipedia.org/wiki/Higher-order_function higher order functions] among languages that handle functions as first class objects. Basically blocks can be designed for loop abstraction and lets the user to design their own way of iterating the values, thereby hiding the implementation details.  
Blocks are basically nameless functions which can be passed to a function and then that function can invoke the passed in nameless function. This is a common style called [http://en.wikipedia.org/wiki/Higher-order_function higher order functions] among languages that handle functions as first class objects. Basically blocks can be designed for loop abstraction and lets the user to design their own way of iterating the values, thereby hiding the implementation details.  
Line 341: Line 381:
=== Clojure ===
=== Clojure ===


= Conclusion =
Clojure[[http://oreilly.com/catalog/9781934356333 31]] is also a functional programming language, and it is a dialect of Lisp. It is not a pure functional language. Instead, it is a dynamically typed language. Just like Java it runs on JVM platform, but its syntax differs from Java. It is represented as :


= References =
 
 
 
 
= Mixing Functional & O-O code =
 
This chapter deals with the mixing of functional and object-oriented programming paradigms. We start with listing the different programming paradigms available today. We introduce functional and object-oriented approaches briefly and then discuss the advantages of one over the other. Following this, we discuss some aspects and features of mixing both the approaches. Finally, we talk about few languages that constitute such a mix.


== Programming Paradigms Today==
(functions arguments...)


Several programmatic approaches to solve a particular task lead to distinct programming paradigms like, <br>
* [http://en.wikipedia.org/wiki/Imperative_programming Imperative Programming] <br>
* Functional programming<br>
* Object Oriented programming<br>
* [http://en.wikipedia.org/wiki/Logic_programming Logical programming], etc.  <br><br>
Lets focus on functional and object oriented programming approaches.


== Functional Programming ==


[http://en.wikipedia.org/wiki/Functional_programming Functional programming] is the task of decomposing a problem into a number of functions. Selectively executing these functions results in the solution to the problem. The functions mostly behave as mathematical. For given set of inputs the program should always return the same output. It usually concentrates on what type of problem we are dealing with rather than on the details of how to solve the problem. For example lets say there is a function which calculates area of a square. If we use it six times then we end up with area of a cube. Thus functional programming helps to build complex systems.
The function and its arguments are enclosed in paranthesis. It has features like immutable data structures, high-order functions, recursion, and easy and fast java interoperability.  


=== Approach ===
In Clojure's model, value calculation is purely functional. Values never change. New values are functions of old. 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, functional value calculation is independent of identity-value association. This makes clojure easier to understand and test.


Expressions are the collection of variables and operations resulting in a single value this also deals with the way of solving the problem as expressions. Hence also called Expression related programming. It is structured as expression where each expression can be encapsulated in another yielding the result. Making the change in data structures as the program runs is called [http://en.wikipedia.org/wiki/Side_effect_(computer_science) side effects]. Purely functional language has no side effects. Language like Haskell is a pure functional language . Some languages need many approaches for achieving the desired result. Such languages are multi-paradigm. Examples for such languages are C++, Python,Lisp. Its like evaluating an expression and use the resulting value for something.
====Example Using Functional Technique in Clojure====


Structure of functional programming :
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)


  (fn2 ( fn1 ()[input list] ) [])  => fn1 takes input list and the output of fn1 is used as input to fn2. Its a schematic representation of
Here,'''''defn make-adder [x]''''' defines a function called ''make-adder''.'''''let [y x]''''' gives a local name y for the value x. Since the scope of any local names is lexical, 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.
                                      how functional programming works.
''
'''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


Functional programming feature (Python) :
====Example Using Object-Oriented Technique in Clojure====


  m = map(lambda i : i*i , numbers)
The following program implements Run-Time Polymorphism which is an object-oriented programming concept.
where ''numbers'' is an array of numbers and ''lambda'' is [http://en.wikipedia.org/wiki/Closure_%28computer_science%29 closure].
(defmulti encounter (fn [x y] [(:Species x) (:Species y)]))
 
(defmethod encounter [:Bunny :Lion] [b l] :run-away)
Python has some functions like map, filter, reduce to support functional programming style. In the example above, the 'map' is a high-order function that takes a function and an array of numbers as input. The ''lambda'' takes i as input and returns i*i as output. Every result returned is appended to a list and produced as output. In functional programming, the programmer is given a natural framework for developing smaller, simpler, and more general modules, which are then glued together.
(defmethod encounter [:Lion :Bunny] [l b] :eat)
 
(defmethod encounter [:Lion :Lion] [l1 l2] :fight)
== Object Oriented Programming ==
(defmethod encounter [:Bunny :Bunny] [b1 b2] :mate)
 
(def b1 {:Species :Bunny :other :stuff})
[http://en.wikipedia.org/wiki/Object-oriented_programming Object-oriented programming] is a programming technique where everything is defined as an object. Objects are well-defined discrete bundles of data(attributes) and the associated functions(behavior). They are devised to resemble real-life objects and are uniquely identifiable by a name. The attributes could be of simple datatype(int, String, Boolean) or objects themselves. The behavior is defined by methods to use and manipulate the attributes. The values of attributes of an object at an instant is the state of the object. OO Programming allows objects to have their state retained throughout the code until manipulated otherwise. Objects are capable of housekeeping their own states, interacting and establishing relationships with other objects, inheriting, etc.
(def b2 {:Species :Bunny :other :stuff})
 
(def l1 {:Species :Lion :other :stuff})
=== Fundamental concepts ===
(def l2 {:Species :Lion :other :stuff})
 
A [http://en.wikipedia.org/wiki/Class_%28computer_science%29 class] is a user-defined datatype that provides implementation details to define the attributes and their properties. It is an abstract representation of an object(i.e.,) like a mold for objects.
An instance is an executable copy of a class. They are the actual objects created using the ‘class mold’ on run time.
Methods are a set of procedural statements or functions to define the behavior of an object, convey the current state, modify values of the attributes, etc.
 
Example :
 
An object in Java might look like this:
 
public class Person {
  private String name;
  public Person() {
  }
  public void setName(String name) {
      this.name = name;
  }
  public String getName() {
      return this.name;
  }
}
 
Here, OO Programming allows the programmer to set the ''name'' attribute of the class ''Person'' and get the name whenever needed in the code. An object of this class Person will remain in memory forever as long as there is a reference to it. As OO Programming allows objects to have their state retained, the value of the ''name'' attribute for a particular ''Person'' object remains the same across any part of the code until it is set differently.
 
=== Features ===
 
Three primary characteristics of object oriented programming are Encapsulation, Polymorphism, and Inheritance.
[http://en.wikipedia.org/wiki/Encapsulation_%28object-oriented_programming%29 Encapsulation] is the ability of objects to hide visibility of their attributes and behavior, thereby providing service independent of implementation.
[http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming Polymorphism] allows identical operations to behave differently in different contexts. The operations that can be performed on an object make up its interface. They enable addressing of operations with the same name in different objects.
[http://en.wikipedia.org/wiki/Inheritance_%28object-oriented_programming%29 Inheritance] is one where an existing type can be used to derive a new type. Derived types inherit the data and operations of the super-type. And also, they can overwrite existing operations or add new ones.
 
There are other important features of O-O programming like [http://en.wikipedia.org/wiki/Message_passing message passing], [http://en.wikipedia.org/wiki/Abstraction abstraction], delegation, etc.
 
Now, we have seen both the approaches and their features in brief. Lets discuss the advantages of one over the other.
 
== Advantages ==
 
=== Functional Approach over OO Approach[[http://www.jot.fm/issues/issue_2009_09/article5.pdf 8]]===
* Functional programming solves the problem with lesser number of lines of code than the OO programming style.<br>
* There is no side effect as they use immutable data structures also called [http://en.wikipedia.org/wiki/Persistent_data_structure Persistent Data Structure] which will have no change in the state of variables. Hence program dont have to depend on history.<br>
* There is no limit in the numeric types used as opposed to OO languages which mainly depend on primitive data types.<br>
* A programmer is given the freedom to think in terms of what to solve in the problem rather than concentrating on how to solve and the flow of the program.<br>
* Suitable for calculation intensive programs.
 
=== OO Approach over Functional Approach===
* Everything can be represented in an object and it has the attributes associated with it and hence the state of the object is known at any time.<br>
* A complex system can be subdivided into modules of objects where as in functional approach, many functions inter operate to form a complex system.<br>
* [http://en.wikipedia.org/wiki/Reusability Re-usability] (i.e.) OO approach enables programmers to create new objects that inherits many of its features from existing objects. This makes object-oriented programs easier to modify than functional.<br>
* [http://en.wikipedia.org/wiki/Debug Debugging] in Object Oriented environment is easy compared with functional approach where a small error in one function causes the whole system (i.e. all the functions) to fail.<br>
* Suitable for making application-oriented software. <br>
 
Both the approaches have their advantages and disadvantages. What if we could get the best of both the worlds? The next section deals with the aspects and features of how well both the approaches are mixed together in some languages.
 
== Mixing Functional & OO Code - Best of both the worlds ==
 
Languages that are a mix of functional and object oriented approaches(eg. Scala[[http://www.scala-lang.org/node/1305 1]], Clojure[[http://oreilly.com/catalog/9781934356333 10]], etc.) make use of best of both the worlds. They support various aspects of functional and object oriented approaches. They have a bunch of functional approach features[[http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.56.1464&rep=rep1&type=pdf 6]], which object oriented programming languages(like Java) lack which includes closures. Closures are first-class functions with free variables that are bound in the lexical environment. These languages also sport a very malleable syntax that makes them well suited for "domain specific languages" with the benefits of static typing. They are more expressive, extensible and allow reuse of programming abstractions.
 
Certain languages like Scala, Clojure, etc run on Java Virtual Machine(JVM) ensuring portability to all underlying platforms. They even support immutable objects. In Scala, new language constructs can be added in the form of libraries. They allow safe reuse[[http://www.cs.purdue.edu/homes/jv/510s05/papers/shriram-ecoop98.pdf 9]] of programming abstractions and type-safe extension of software.
 
===Lambda===
 
A lambda[[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1968.pdf 5]] expression is an anonymous function that contain expressions and statements, and can be used to create delegates or expression  types. Such kind of anonymous function can be defined and passed around as easily as other data types and can be used to contain functionality that need not be named. Some notable examples include closures[[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1968.pdf 5]] and currying. Lambda functions with no name can be called using the variable assigned to it.
 
  g = lambda x: x*2 
  g(3)=6
 
We can have lambda function without assigning it to a variable which can be used as inline-function.
 
  (lambda x: x*2)(3)
 
In [http://en.wikipedia.org/wiki/Clojure Clojure] as a functional language, the creation of a chunk of behavior that can be assigned to a variable (known as a lambda) is trivial. Below are two ways to create a lambda that returns the square of its argument.
 
  (def square1 (fn [n] (* n n)))
  (def square2 #(* % %))
 
===Currying ===
 
[http://en.wikipedia.org/wiki/Currying Currying] transforms a function that takes multiple parameters into a chain of functions, each taking a single parameter. It reuses a partially applied function where the function is originally defined as accepting n parameters.It can be interpreted as the technique to decompose a function that takes n parameters into n function each of them taking 1 parameter. For example to say in algebraic terms,consider the function f which takes 3 parameters x,y,z and Currying means that we can rewrite the function as a composition of 3 functions:
 
  f(x,y,z) = 4*x+3*y+2*z
  f(x)(y)(z) = 2*z+(3*y+(4*x))
 
In Scala, currying takes advantage of Scala’s syntactic sugar. Below is a currying example in Scala. This function creates a multiplier function which takes two arguments and partially defines it by assigning a constant to one argument and assigning it to a variable .Later the function is called by assigning the second argument.
 
  def multiplier(i: Int)(factor: Int) = i * factor => method named multiplier which takes two parameters is defined
  val byFive = multiplier(5) _                    => The method is redefined with accepting one parameter and store it in a variable.
  val byTen = multiplier(10) _
 
  scala> byFive(2)                                => Method called by giving the second parameter.
  res4: Int = 10
 
  scala> byTen(2)
  res5: Int = 20
 
===Less Verbosity===
 
In Java each variable should have its type defined beforehand. Whereas in languages like Scala, it is more concise and easier to read than the equivalent Java.
 
For example,  a Map can be created with a simple syntax in Scala,Clojure than in Java:
 
<table>
<tr>
<td>
'''Java'''
Map<String, Integer> nMap = new HashMap<String, Integer>();
nMap.put("one", 1);
nMap.put("two", 2);
nMap.put("three", 3);
</td>
<td>
'''Scala'''
 
var nMap = Map("one" -> 1, "two" -> 2, "three" -> 3)
   
   
   
  (encounter b1 l1)
   
  -> :run-away
</td>
  (encounter l1 l2)
<td>
  -> :fight
'''Clojure'''
   
(doto (new Java.util.HashMap)(.put “a” 1)(.put “b” 2))
   
 
</td>
</tr>
</table>
 
Here, Scala compiler knows that nMap uses Strings as keys, and Integers as values. Unlike Java, this need not be specified beforehand. Scala could figure it out itself. Moreover, Scala will give an error if a different key-value pair is tried to insert. This is called "type inference". This prevents a whole class of bugs at run time just like Java but with less verbosity.
In a similar way Clojure also involves only few lines of code compared with the object oriented Java language which takes many lines of code.A simple Clojure example and the associated Java code :
Example
 
  (defn blank? [s] (every? #(Character/isWhitespace %) s))


The innermost function Character/isWhiteSpace checks the first argument % for any whitespace and returns true if it is. every? invoke the above inner function for all elements in the collection s.It has no variables, no branches etc.
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.


Java code
=== Summary of Languages Supporting Mixing ===
isBlank() method checks to see whether a string is blank or contains only whitespace.
 
  public class Stringcheck{
    public static boolean isBlank(String str){
          int len;
          if(str==null || (strlen =str.length())==0)
              return true;
          for(int i=0; i<strlen;i++) {
                if((Character.isWhitespace(str.charAt(i))==false)){
                        return false;
                    }
            }
        return true;
      }
  }
 
=== Pattern Matching ===
 
To say simply, a [http://en.wikipedia.org/wiki/Pattern_matching Pattern matching] is a technique to search string for the occurrence of any patterns or regularity. Pattern matching is an elegant way to decompose objects into their constituent parts for processing.Many languages support the concept of pattern matching. Perl supports pattern matching using the pattern definition mini language called regular expressions, also called regexes  or  REs, which is borrowed from the regular expressions used in many Unix tools, such as  grep()  and  sed().The risk that the parts of an object might be changed outside of the control of the enclosing object is avoided. For example, if there is a Person class that contains a list of addresses, it will not be an issue to expose that list to clients if the list is immutable. The users will not be able to change the list  unexpectedly.Given below is a simple example for pattern matching used in Perl:
 
$mystring = "Hello world!";  // Perls way of assigning string to a variable.
if($mystring =~ m/World/) { print "Yes"; } // Checks the string stored in variable mystring has the string "World".
$mystring =~ s/world/mom/; // Replaces the string "world" stored in mystring to mom.
 
Another sample of regular expression in java :
 
String mystring="Hello World" ;
Pattern str = Pattern.compile("\\w+");  => Pattern stored for matching.
Matcher fit = str.matcher(mystring);    => Matcher class which perform matching of the string with the pattern defined.
if(fit.matches())
 
As languages like Scala and Clojure support procedural code, pattern matching is done as equal or with less difficulty compared with Java which needs to use regex. Scala can even be embedded into XML as its syntax is somewhat similar.Given below an overview of how regular expression is achieved in Clojure.
Data are manipulated in Clojure through the sequence called seq which is a logical list. Clojure can access java collections, its collections, Regular expression matches via the seq also called seq-able. Clojure's regular expression uses java.util.regex library at the lowest level. For achieving that the keyword re-seq is used.
Syntax:
  (re-seq regexp string)
Example
  (re-seq #"\w+" "Hello World") => ("Hello" "World")  => #"\w+" represents the java.util.regex.Pattern
 
=== Java Interoperability ===
Considering Clojure, it gives clean, simple and direct access to java and can access Java API directly.Clojure doesnot wrap Java's string functions. We can call using Java interop forms. It provides syntax for accessing Java elements like classes, instances, constructors, methods and fields and can also wrap Java API. The “.” dot special form is used for accessing Java. Some Clojure syntax which can access Java API:<br>


Each of the languages contains both functional and object-oriented features. The following table shows how each of the languages have both functional and object-oriented characterics. Not all characteristics of the languages are listed, but enough to demonstrate that the languages each have different ways of mixing object-oriented and functional techniques.


{| class="wikitable" border="2"
{| class="wikitable" border="2"
|-
|-
Java
!   
Clojure
Functional Characteristics
|-
!  Object-Oriented Characteristics
| new Widget(“red”)
| (new Widget “red”)
|-
|-
| Math.PI
! Scala
| (.Math PI) or  Math/PI
| Immutable objects, the ability to pass functions as parameters, implicits, closures.
| Every value is a object, mutable objects.
|-
|-
| System.currentTimeMillis()
! Ruby
| (.System currentTimeMillis) or System/currentTimeMillis
| Functional programming used in blocks.
| Everything is an object.
|-
|-
| rnd.nextInt()
! Clojure
| (.rnd nextInt) or (.nextInt rnd)
| Immutable data structures, high-order functions, recursion.
| Objects, runtime polymorphism, [http://en.wikipedia.org/wiki/Multiple_dispatch multimethods.]
|-
|-
|}
|}


= Conclusion =
In summary, functional and object-oriented programming can be successfully mixed in programs. Many functional techniques are useful in object-oriented programs. Functional programming integrated with object oriented style leads to:


Clojure pass functions as arguments to other functions. But Java does not support this. So Clojure provides a member function memfn macro to wrap methods or can use anonymous function to wrap a method call.
*Better understanding of program behavior and easier debugging as a result of immutability features
    (map (memfn toUpperCase) [“a” ,”short”,”message”])
*Use of techniques such as blocks and closures to implement object oriented design and reduce repetitive code
or
*Lesser complexity and reduction in the number of lines of code
    (map #(.toUpperCase %)[“a”,”short”,”message”]) => #(body) represents the anonymous function in Clojure.


For example,
Languages such as Scala, Ruby, and Clojure effectively support mixing these two paradigms, allowing programmers to create cleaner, less buggy object-oriented code.
    (def the-digits
    (map #(Integer. (str %))(filter #(Character/isDigit %) (seq big-num-str))))
    where (def big-num-str (str "123785334434se9088af8309304293872adbcdfd”))


The above code extracts the integers from string and discards the non-numeric characters. Lets look at the functions defined in the example. There are totally five functions defined.They are
= References =
    (seq big-num-str)          => get each character defined in big-num-str
    (Character/isDigit %)      => Checks whether the input is an integer
    (filter #())              => Filter each string from str
    (map #(Integer. (str %)))  => Change the string to integer
    (def the-digits)          => Output the integers only in a string of characters.   
Here,
    #(Character/isDigit) represents the Java method Character.isDigit() and #(Integer.(str %)) represents the new java.lang.Integer(str(%))
 
Most of the Clojure library functions have defined semantics for objects of Java types. contains? and .get work on Java’s  Maps, arrays, Strings, count works on Java Strings, Collections and arrays. Clojure is built around these aspects. It avails the performance of JVM and the richness of both the core APIs and the numerous third-party libraries written in the Java language and restrained from reinventing them.
 
=== Multiple Inheritance ===
 
[http://en.wikipedia.org/wiki/Multiple_inheritance Multiple Inheritance][http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.23.4735&rep=rep1&type=pdf 2] is the concept of using the methods and variables of more than one superclass to a sub class.Java was designed without multiple inheritance. But Java supports the solution of problems commonly solved with multiple inheritance in other ways with help of interfaces where the methods defined in it are not implemented.In Scala, classes are extended by subclassing and a flexible mixin-based composition mechanism as a clean replacement for multiple inheritance in Java.Lets see how multiple inheritance achieved in Scala:
 
As interfaces in Java, Scala allows traits but has some methods partially implemented. The only difference to classes is the traits may not have constructor parameters.
 
  trait Similarity {
  def isSimilar(x: Any): Boolean  // not implemented
  def isNotSimilar(x: Any): Boolean = !isSimilar(x) //implemented method
  }
 
This trait defines two methods isSimilar and isNotSimilar where isSimilar does not provide a concrete method implementation (it is abstract in the terminology of Java), and the method isNotSimilar defines a concrete implementation. Consequently, classes that integrate this trait only have to provide a concrete implementation for isSimilar.
 
  class Point(xc: Int, yc: Int) extends Similarity {
    var x: Int = xc
    var y: Int = yc
    def isSimilar(obj: Any) =  //need to implement the method here
    obj.isInstanceOf[Point] &&
    obj.asInstanceOf[Point].x == x
  }
 
  object TraitsTest extends Application {
    val p1 = new Point(2, 3)
    val p2 = new Point(2, 4)
    val p3 = new Point(3, 3)
    println(p1.isNotSimilar(p2))
    println(p1.isNotSimilar(p3))  //uses the already defined method
    println(p1.isNotSimilar(2))
  }
 
These are some of the aspects and traits of mixing functional and object-oriented approaches. As we discussed in the advantages section, both the approaches have their benefits and limitations. Mixing them aspect-wise enables the above features in such languages. Lets discuss those languages briefly in the next section.
 
== Languages Supporting Functional and OO code ==
 
OCaml and F#[[http://msdn.microsoft.com/en-us/library/dd233154.aspx 7]] are some of the languages which support both functional and object oriented programming. OCaml is as fast as C and its featured as [http://www.haskell.org/ Haskell] which is a pure functional language. F#[[http://oreilly.com/catalog/9780596153656 3]] is a dynamically typed language which can run on .NET framework and has supported immutable types i.e. tuples, records, discriminated unions and lists  to work in Functional programming. It has functions that can either be in curried or in uncurried form. As in functional language it can pass functions as arguments to other functions, resulting in higher order functions. It also supports lambda functions and closures. F#,behaves like other .NET languages as both in imperative and object oriented style.<br>
 
Clojure[[http://oreilly.com/catalog/9781934356333 10]] is also a functional programming language and it is a dialect of Lisp. It is not a pure functional language and it is a dynamically typed language. Just like Java it runs on JVM platform. But its syntax differs from Java. It is represented as :
 
  (functions arguments...)
 
The function followed by its arguments is enclosed in paranthesis. It has features like immutable data structures, high-order functions and recursion, easy and fast java interoperability. <br>
 
Python and Ruby are also the programming languages which offer the mix of functional and OO languages. But these languages doesn't support the algebraic data types and pattern matching.
 
==Conclusion ==
The above aspects of functional and object oriented programming techniques discuss some if their merits and demerits. Mixing them produces a new programming paradigm which leads to a new dimension in programming. A few fundamental concepts are explored in Clojure and Scala here. The ability of Clojure and Scala to run in JVM platform makes them more preferable than others in the market. Some of the merits like closure, less verbosity, high order functions, currying along with interoperation with previously written libraries in these languages make them more efficient and useful. There are also other languages which support functional and object oriented techniques. Mixing the approaches, evolve a new dimension in programming which is practical and opens doors to more exploration.


== References ==
Special thanks to writers of previous wiki pages (see last three references below).


#[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]
# [http://www.scala-lang.org/node/1305 Bagwell. Learning Scala. Available from http://www.scala-lang.org/node/1305 (2009); Accessed 24 April 2010.]
# [http://www.scala-lang.org/node/1305 Bagwell. Learning Scala. Available from http://www.scala-lang.org/node/1305 (2009); Accessed 24 April 2010.]
# [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.23.4735&rep=rep1&type=pdf  Bjarne Stroustrup. Multiple Inheritance for C++. 1999.]
# [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.23.4735&rep=rep1&type=pdf  Bjarne Stroustrup. Multiple Inheritance for C++. 1999.]
Line 664: Line 497:
# [http://www.cs.purdue.edu/homes/jv/510s05/papers/shriram-ecoop98.pdf Shriram Krishnamurthi, Matthias Felleisen, Daniel P. Friedman. Synthesizing Object-Oriented and Functional Design to Promote Re-use. European Conference on Object-Oriented Programming, 1998.]
# [http://www.cs.purdue.edu/homes/jv/510s05/papers/shriram-ecoop98.pdf Shriram Krishnamurthi, Matthias Felleisen, Daniel P. Friedman. Synthesizing Object-Oriented and Functional Design to Promote Re-use. European Conference on Object-Oriented Programming, 1998.]
# [http://oreilly.com/catalog/9781934356333 Stuart Hallway. Programming Clojure. Pragmatic Bookshelf, USA, 2009.]
# [http://oreilly.com/catalog/9781934356333 Stuart Hallway. Programming Clojure. Pragmatic Bookshelf, USA, 2009.]
#O'Reilly (2009), "Programming Scala", ''O'Reilly Media Inc.''.
#Dave Thomas, Chad Fowler, Andy Hunt (2006) ''Programming Ruby'', The Pragmatic Bookshelf.
#[http://lamp.epfl.ch/~phaller/doc/haller10-Translucent_functions.pdf Philipp Halle, Lightweight language support for type-based, concurrent event processing, Lausanne, Switzerland, April 2010.]
#[http://biblion.epfl.ch/EPFL/theses/2007/3899/EPFL_TH3899.pdf Burak Emir, Object-Oriented Pattern Matching, EPFL, October 2007].
#[http://math.hws.edu/eck/cs124/downloads/OOP2_from_Univ_KwaZulu-Natal.pdf, Object-Oriented Programming,February 2007].
#[http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2010/ch1_1e_az CSC/ECE 517 Fall 2010/ch1 1e az]
#[http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2010/ch1_1e_AE CSC/ECE 517 Fall 2010/ch1 1e AE]
#[http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2010/ch1_1e_bb CSC/ECE 517 Fall 2010/ch1 1e bb]

Latest revision as of 00:19, 20 September 2012

Introduction

This wiki page explores the idea of mixing functional and object-oriented code. Mixing different programming paradigms is called multi-paradigm programming. There are four major paradigms:

In this wiki we explain how functional and object-oriented paradigms can be mixed. First, we explain what functional and object-oriented style programming is. Secondly, we will show how to apply functional techniques to object-oriented programming. Lastly, we discuss languages that support mixing functional and object-oriented code.

Functional Programming

Functional programming treats computation as the evaluation of mathematical functions. It is compute-centric rather than data-centric. Functional programming keeps no global state, does not use for or while loops, and mandates that data is immutable. Instead, everything is done using functions, usually functions that evaluate mathematical expressions. Each of these functions maintain no internal state and will always produce the same output given the same input.

Example Contrasting Imperitive and Functional Styles

Let's look at an example. Suppose we have a list of numbers and we want to multiply each number in the list by 2. The first approach is the imperitive style:

    array[] = {1,2,3,4,5}
   for(i=0 ; i<array.length; i++){
      array[i] = array[i] * 2;
   }

In the above example, array[] is a global variable. If we fail to check the array length, then a runtime exception occurs which might result in the program being crashed. As far as functional style, there is a function called map(func,seq)(in python language) where the function 'func' is applied to each member of seq. The following code is written in a functional style.

     numbers = [1,2,3,4,5]
    /*  define a method called compute on each number in the list */
    def compute(var):
        var = var * 2
        return var
    /* Now call the map function */
    L = map(compute,numbers)
    print L                   // L will print [1,4,6,8,10]

Notice that there is no global data nor any nested loops and the bound checking is handled internally within the map function. The programmer is relieved of of runtime errors and thus can debug the program easily.

Advantages of Functional Programming

Some advantages of this approach are:

  • Easier debugging: Since every thing is broken down into small simple functions, the functions are often easy to debug.
  • More compact code: Functional programming typically requires fewer lines of code. Since compution is done by function code reuse is prevelent.
  • Nothing depends on state: Because functional programs keep no state information, the functions will always operate the same regardless of the past history of the program.

Object-oriented Programming

Object-oriented programming (OOP) is a programming paradigm organized around interacting "objects"(usually instances of a class) rather than "actions" and data rather than logic. A basic principle of OOP is that a program consists of a list of subroutines which can perform individually.

An object-oriented programming language provides support for the following object-oriented concepts--object, class, interface and inheritance. To illustrate this idea clearly and vividly let's review the following example-- your limbs. The "Limbs" is a class. Your body has two objects of type "limbs", named arms and legs. Their main functions are controlled/ managed by a set of biological signals sent from central nervous system( through an interface). So the nervous system is an interface which your body uses to interact with your limbs. The "limbs" is a well architected class. The "legs" has a subclass which contains "left leg" and "Right leg". The "legs" is being re-used to create the left leg and right leg by slightly changing the properties of it. If the "legs" owns attributes like length, color of skin etc, then the subclass, which contains "left leg" and "right leg" in this case, automatically inherit these attributes( that is called inheritance).

We could code in object-oriented paradigm as:

 class Limbs  
 #define a class of limbs
   def initialize(limbs,length,colorofskin)
   @limbs=limbs
   @length=length
   @colorofskin=colorofskin
   end
 end
 limbs=Limbs.new("legs","100cm","white")  
 #create a new object in class "Limbs"
 class Legs<Limbs   
 #create a subclass "Legs",which belong to class"Limbs"
   def initialize(legs,length,colorofskin)
     super(length,colorofskin)
     @legs=legs
   end 
 end
 legs=legs.new("left leg") 
 #create a new object in class of "Legs"

Features of Object-oriented Programming

  • Inheritance. A programmer can simply create a new object that inherits many of its features from super-class. And also, they can overwrite existing operations or add new ones.This makes object-oriented programs easier to modify.
  • Encapsulation.This refers to hiding the internal representation of the object from the outside view. You can hide unnecessary implementation details from the object user. One of the benefits of encapsulation is data protection.
  • Polymorphism.This allows identical operations to behave differently in different contexts. The operations that can be performed on an object make up its interface. They enable addressing of operations with the same name in different objects. Consider the operator '+', for numbers it will generate the sum, but for strings it will produce a third string which concatenates the input strings.

Advantages of Object-oriented Programming

  • Simplicity: we use software objects to simulate real world objects, so the complexity is reduced and the program structure is very clear.
  • Modularity: each object forms a separate entity whose internal workings are decoupled from other parts of the system.
  • Modifiability: programmers can easily make minor changes in the data representation or operations in an OOP. Changes inside a class do not affect any other part of a program, since the only public interface that the external world has to a class is through the use of methods.
  • Extensibility: adding new features or responding to changing operating environments can be solved by introducing a few new objects and modifying some existing ones.
  • Maintainability: objects can be maintained separately, making locating and fixing problems easier.
  • Re-usability: objects can be reused in different programs.

Mixing Functional and Object-Oriented Programming

In object-oriented world, data and operations are grouped together into modular units called objects and we combine objects into structured networks to form a program. The results are depend on arguments and objects' state at method invocation time. While in functional world, the basic elements are variables in the mathematical sense and functions in the mathematical sense. Functional programming can reduce side-effects. If there is no side-effects, it means your can apply the function at anywhere freely. No matter how you apply this function, the same input arguments produce the same results.

Functional - Mathematical Functions Object-Oriented - Objects
Compact Modular
Easy to debug Easy to maintain

Overall, object-oriented programming requires more upfront design, but is easier to maintain long-term. Obviously if we apply functional programming techniques to object-oriented programming, everything can be done better--the code is easier to write, runs faster, and uses less memory.

Functional Techniques useful for Object-Oriented Programming

According to above-mentioned information, we can perform functional programming on an object-oriented programming language because: 1). object can have constant state 2). method can depend only on its arguments and context available at method definition time

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. One of the cornerstone of mixing functional and object-oriented code is treating functions as objects.It means that we can pass functions as arguments, store it and return them from other functions. This is highly useful in an user interface code where it can be used as call back functions which gets called when an event occurs(event driven programming).

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.

Lambda Calculus

Lambda calculus is the most critical basis of functional programming. A lambda expression is an anonymous expression that contain expressions and statements.Each expression stands for a function with one parameter.

Let consider the following function:

 def f(x)
 return x**2 
 print f(4)

We can use a lambda calculus to compute this expression without assigning it to a variable:

 (lambda x:x**x)(4)  

We can see that these two code snippets have the same results. It is more concise and flexible to define with lambda. The above is a pure functional approach. In order to make code more state-less and concise, lambdas can be embedded inside the object-oriented language. The below code in Python demonstrates the use of lambda in a closure:

 def fun(x):
   return x%3==0
   str=[2, 18, 9, 22, 17, 24, 8, 12, 27]
   filter(fun,str)

The above code works to find numbers which are divisible by 3. We can simplify the code by the use of lambda as following:

 str=[2, 18, 9, 22, 17, 24, 8, 12, 27]
 print filter(lambda x: x%3==0, str)

Currying

In the above information we have learned much about lambda calculus, which take care of one argument, now let me introduce you another concept called currying functions which takes in multiple arguments and returns a chain of functions with lesser number of arguments. It can be interpreted as the technique to decompose a function that takes n parameters into n functions and each of the n functions takes one parameter.

Currying is really an interesting concept. Let's take a sample code in JavaScript to understand it:

 //This is a function for calculating x+y. The difference between this function and general is that this is a currying function.
 function add(x, y)
 {
 if(x!=null && y!=null) return x + y;
 else if(x!=null && y==null) return function(y)
  { 
    return x + y;  //return a closure with parameter y for subsequent calculations
   }
 else if(x==null && y!=null) return function(x)
  {
    return x + y;  //return a closure with parameter x for subsequent calculations
   }
  }
 var a = add(3, 4);  //compute the value of (3+4) and return the value of 7
 var b = add(2);  //add(2) is equal to a function of (2+y)
 var c = b(10);  //pass 10 to y, and return the value of (2+10) which is 12

In the above sample, b=add(2) gives us a currying function of add(), which is function of y when x=2.

More interestingly, we can define a currying form of arbitrary functions.

 function Foo(x, y, z, w)
 {
  var args = arguments;
  if(Foo.length < args.length)
    return function()
   {
     return args.callee.apply(Array.apply([], args).concat(Array.apply([], arguments)));
   }
  else
    return x + y – z * w;
  }

Pattern Matching

What is pattern matching? I think all of you do know what it is, you just don't know you know it. The semantics are equally straightforward.Firstly, we evaluate the value expression, then we walk down the clauses. For each one, we see if the pattern matches the value. If so, we execute the body and end. Simply put, pattern matching is a technique to search string for the occurrence of any patterns or regularity.

Pattern matching allows you to do different calculations according to different identifier values. It looks the same with nests of "if...else" statements, as well as "switch" statements in C++ and C#. But here it is much stronger and more flexible.

You may find that there are two main types of usage of pattern matching:

  • To search and find a particular value.
  • To find a particular value and replace it with selected text.

For example, the following code snippets writes a message if a string contains the text Perl or Python:

 if line =~ /Perl|Python/
 puts "Scripting language mentioned:#{line}"  
 end

Next, let us consider the following sample in which a part of a string matched by a regular expression can be replaced with different text using one of Ruby’s substitution methods:

 line.sub(/Perl/, 'Ruby') # replace first 'Perl' with 'Ruby'
 line.gsub(/Python/, 'Ruby') # replace every 'Python' with 'Ruby'

Advantages of Pattern Matching:

  • It allows concise, readable deconstruction of complex data structures.
  • It gives a possible separation of data structure and respective functionality.

Examples of Mixing

A number of programming languages support mixing of both functional and object-oriented code. Three of these (Scala, Ruby, and Conjure), are described in more detail below.

Scala

Scala is a modern multi-paradigm 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. Scala was conceived in 2001 and implemented by Martin Odersky. It supports mixing functional and object-oriented code.

Mixing Functional and Object-Oriented Code in Scala

Scala is a strange specimen. It is a complete blend of object-oriented and functional programming. How can this happen? The functional world advocates immutability, but the object-oriented world focuses on the state and how to change it to fit your needs. Scala allows you create both mutable and immutable objects. Consider the following example,

val str: String = "Hello World"

In the first line, an immutable version(a misnomer indeed) of str is being created . A rough translation into Java is below:

final String str = "Hello World"; //note the extra semi-colon

Consider the next example below,

val list: List[String] = List("Scala", "is", "the coolest", "language", "in the world!")

The same code can be written in Java as:

 List<String> mutableList = new ArrayList<String>();
 list.add("Scala");
 list.add("is");
 list.add("the coolest");
 list.add("language");
 list.add("in the world!");
 List<String> immutableList = Collections.immutableList(mutableList);

Compared to Java, Scala reduces the total number of lines you need to type and at the same time looks much simpler and less verbose. Even though the above example shows an immutable collection, scala also provides mutable collections and object types in the package scala.collection.mutable.*

As can be observed, even though Scala advocates immutability, it does not restrict you from creating mutable objects. So it's the best of both worlds. Another part of the functional world is the concept of functions as 'first class members' of the language. Some of the common languages like Ruby, Python and JavaScript all incorporate this feature. In the sense you can pass around functions to methods as a parameter. Enough talking;

Let us have a class say 'Person' which has properties, name and another variable age. In Java:

class Person{
   private String name;
   private int age;
   public String getName(){
       return name;
   }
   public void setName(String s){
       this.name = s;
   }
   public int getAge(){
       return age;
   }
   public void setAge(int age){
       this.age = age;
   }
}

In Scala:

case class Person(name: String, age: Int)

This single line is equivalent to the above java code! Getters for name and age, equals(), and hashCode() method are automatically generated for you by the compiler. Isn't this an awesome feature?

Now assume we have a list of persons and we want to filter out all the persons who are of age 23. How would you do that in Java?

 List<Person> persons; //has a bunch of person objects in it.
 List<Person> twentyThree = new ArrayList<Person>();
 for(Person p: persons){
     if(p.getAge() == 23){
         twentyThree.add(p);
     }
 }

In Scala:

val twentyThree: List[Person] = persons.filter( _.age == 23)

That's it! In case you are wondering whats going on, filter is a method present on scala.List class and the code block _.age == 23 is a function created on the fly and passed onto the filter method. More precisely its called a closure - a functional concept which can be emulated in java only using anonymous inner classes. Scala's compiler transforms our one line function into some anonymous inner classes when generating java byte code, allowing developers to define functions in a simple manner.

In fact, every function is an object in Scala. Scala's standard library has a number of functions which are objects themselves.

Implicits in Scala

In almost all programming languages, there is a necessity to profile the running time of the procedures and tune its performance. The old way of doing things in Java would be:

public class Main{
public static int factorial(int x){
  if(x == 0 || x == 1) return 1
  else return x * factorial(x-1)
 }
 public static void main(String [] args){
   long beforeTime = System.currentTimeMillis();
   int result = factorial(5);
   System.out.println("Total time taken to execute factorial(5) is " + (System.currentTimeMillis() - result)+"ms");
   System.out.println("factorial(5) = " + result);
 }
}

However, if you want to find out the execution time of some other method, you would have to type in all the above lines again. So much for code re-use or DRY (dont't repeat yourself)! Lets see how its done in Scala.

object Main{
 def main(args: Array[String]){
   def factorial(x: Int):Int = x match{
     case 0 | 1 => 1
     case _ => x * factorial(x-1)
 }
 import System.currentTimeMillis
 def timeIt(msg: String = "Time to execute is: ")(func: => Unit){
   val before = currentTimeMillis
   func
   println(msg + (currentTimeMillis - before) + "ms")
 }
 timeIt("Total time taken to execute factorial(5) is "){
     val result = factorial(5)
     println("factorial(5) = " + result)
 }
}
//would print: factorial(5) = 120
// Total time taken to execute factorial(5) is 1ms


That's not right! The function timeIt looks like a feature built into the language. Try saving the above code into a separate file and run it - It will still work. Using this feature, it is possible to build powerful DSL languages which can run at full speed on JVM.

Ruby allows you to add new methods to objects. Since you are splitting open the class and adding/overriding methods (in)|(to) the class, this feature is often called Monkey Patching. Because other libraries may depend on some methods which you changed, often this leads to unexpected behavior at runtime. However, Scala provides yet another feature called implicits which helps you do this better.

In Java, String class is final so there is no way you can add new methods to it. But with implicits you can do more! Suppose you have some text in memory and you know it represents a number. But in Java the usual way to convert string to int is to do a Integer.parseInt(string) which seems so unnecessary. Let us make our lives easier...

 implicit def strToInt(str: String) = new {
   def asInt = Integer.parseInt(str)
 }
 val str = "1234"
 println(str.asInt * 3) //prints out 3702

The above code gives us an impression as if String class has gained new asInt method. Can static object oriented languages do this? No! Infact scala cheats by calling our implicits to convert it into a different object as and when needed.

The above functionalities are purely object oriented, yet they are safe. They don't pollute the global namespace, unlike Ruby or Python.

Ruby

Ruby is another language that, like Scala, supports mixing functional and object-oriented code. It 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.

Ruby Mixing Example

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

Functional Style Coding in Ruby Blocks

Blocks are basically nameless functions which can be passed to a function and then that function can invoke the passed in nameless function. This is a common style called higher order functions among languages that handle functions as first class objects. Basically blocks can be designed for loop abstraction and lets the user to design their own way of iterating the values, thereby hiding the implementation details. For example, if we want to iterate backwards from the end to the beginning without revealing its internal implementations, we could implement the loop logic inside the block and pass it to a method or function.

Here is a Ruby implementation of block:

def printlist(array,&reverse)
   array.each do |element|
      puts "array element: #{element}"
   end
   reverse.call(array)   /* Here it prints the reverse implementation of list*/
   end
 
printlist([1,2,3,4,5,6]) { |array| 
  array.reverse.each do |element| 
    puts "array element: #{element}" 
  end 
}

The statements between { } is a block and it gets called by reverse.call(array)within the printlist method.

Clojure

Clojure[31] is also a functional programming language, and it is a dialect of Lisp. It is not a pure functional language. Instead, it is a dynamically typed language. Just like Java it runs on JVM platform, but its syntax differs from Java. It is represented as :


(functions arguments...)


The function and its arguments are enclosed in paranthesis. It has features like immutable data structures, high-order functions, recursion, and easy and fast java interoperability.

In Clojure's model, value calculation is purely functional. Values never change. New values are functions of old. 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, functional value calculation is independent of identity-value association. This makes clojure easier to understand and test.

Example Using Functional Technique in Clojure

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. Since the scope of any local names is lexical, 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

Example Using Object-Oriented Technique in Clojure

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.

Summary of Languages Supporting Mixing

Each of the languages contains both functional and object-oriented features. The following table shows how each of the languages have both functional and object-oriented characterics. Not all characteristics of the languages are listed, but enough to demonstrate that the languages each have different ways of mixing object-oriented and functional techniques.

Functional Characteristics Object-Oriented Characteristics
Scala Immutable objects, the ability to pass functions as parameters, implicits, closures. Every value is a object, mutable objects.
Ruby Functional programming used in blocks. Everything is an object.
Clojure Immutable data structures, high-order functions, recursion. Objects, runtime polymorphism, multimethods.

Conclusion

In summary, functional and object-oriented programming can be successfully mixed in programs. Many functional techniques are useful in object-oriented programs. Functional programming integrated with object oriented style leads to:

  • Better understanding of program behavior and easier debugging as a result of immutability features
  • Use of techniques such as blocks and closures to implement object oriented design and reduce repetitive code
  • Lesser complexity and reduction in the number of lines of code

Languages such as Scala, Ruby, and Clojure effectively support mixing these two paradigms, allowing programmers to create cleaner, less buggy object-oriented code.

References

Special thanks to writers of previous wiki pages (see last three references below).

  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
  22. Bagwell. Learning Scala. Available from http://www.scala-lang.org/node/1305 (2009); Accessed 24 April 2010.
  23. Bjarne Stroustrup. Multiple Inheritance for C++. 1999.
  24. Chris Smith. Programming F#. O'Reilly Media, Sebastopol, CA, 2009.
  25. Jean E. Sammet, David Hemmendinger. Encyclopedia of Computer Science. John Wiley and Sons Ltd., Chicester, UK, 2003.
  26. Jeremiah Willcock, Jaakko Jarvi, Doug Gregor, Bjarne Stroustrup, Andrew Lumsdaine. Lambda expressions and closures for C++. 2006.
  27. Lee Braine. An Object-Oriented Functional Approach to Information Systems Engineering, Department of Computer Science, University College London.
  28. Microsoft Corporation. Visual F#. Available from http://msdn.microsoft.com/en-us/library/dd233154.aspx (2010)
  29. Ph. Narbel. Functional Programming at Work in Object-Oriented Programming. ETH Zurich, Chair of Software Engineering, Journal of Object Technology, 2009. Vol. 8, No. 6.
  30. Shriram Krishnamurthi, Matthias Felleisen, Daniel P. Friedman. Synthesizing Object-Oriented and Functional Design to Promote Re-use. European Conference on Object-Oriented Programming, 1998.
  31. Stuart Hallway. Programming Clojure. Pragmatic Bookshelf, USA, 2009.
  32. O'Reilly (2009), "Programming Scala", O'Reilly Media Inc..
  33. Dave Thomas, Chad Fowler, Andy Hunt (2006) Programming Ruby, The Pragmatic Bookshelf.
  34. Philipp Halle, Lightweight language support for type-based, concurrent event processing, Lausanne, Switzerland, April 2010.
  35. Burak Emir, Object-Oriented Pattern Matching, EPFL, October 2007.
  36. Object-Oriented Programming,February 2007.
  37. CSC/ECE 517 Fall 2010/ch1 1e az
  38. CSC/ECE 517 Fall 2010/ch1 1e AE
  39. CSC/ECE 517 Fall 2010/ch1 1e bb