CSC/ECE 517 Fall 2010/ch1 1e bb

From Expertiza_Wiki
Jump to navigation Jump to search

Functional Programming

Functional programming treats computation as the evaluation of mathematical functions and avoids state and mutable data.

  • Functional programming decomposes a problem into a set of functions.Input flows through 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.
  • Functional programming breaks 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 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.

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.

Examples of 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 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

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:

  • Lambda Calculus
  • Immutability
  • 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 by using functional code.

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 and 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. While using Lambda functions, there is another concept called curried functions in which a function reduces the term and returns another function with the normal form. In the curried function systems, a function with multiple arguments is expressed using a function whose result is another 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.

The below code demonstrates the use of both Functional and Object Oriented Approaches in a code:

 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 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)

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.

Programming Languages supporting both Object Oriented and Functional approach

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

Languages like Scala, Clojure, F#, Ruby etc. support both Functional and Object Orientedapproaches. 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. 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 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 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.

 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 Application class can be used to quickly turn objects into executable programs. 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.

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.


Ruby

Ruby is a dynamically typed Object Oriented Language which contains the features of Perl and Smalltalk. Ruby 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. In Object-oriented programming, properties are associated with instance variables and actions with methods. 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. This closure block has become one of the most popular features of the Ruby Programming Language making it a truly mixed approach language.

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. This is being widely used in applications nowadays.

References