Representative Functional Languages and Their Features
Functional Languages Any programming language supports and/or encourages functional programming is called a functional language. What is functional programming? A functional program is simply an expression, and executing the program means evaluating the expression. In imperative ...
Functional Languages
Any programming language supports and/or encourages functional programming is called a functional language.
What is functional programming?
A functional program is simply an expression, and executing the program means evaluating the expression.
In imperative programming, execute a function may result in different values in different time. It is because imperative programming relies on modifying the state through a sequence of commands.
In contrast, execute a function f(x) twice in functional code will give the same output in any given time. Since there is no assignment in functional programming, therefore, no variables to assign and no state is changed (no side effect).
Representative Functional Languages
There are more than 20 functional languages you can find here
In this article we will explore an purely functional language (Haskell) and a mix of imperative and functional language (Ruby)
Haskell
Haskell is a purely functional language, which means that in general, functions in Haskell do not have side effects.
Haskell has some handy features:
- Pattern matching
- Lazy evaluation
- List comprehension
Pattern Matching
Haskell has a cool way to construct function by using Pattern Matching. Pattern Matching are ordered set of patterns which data should conform and will be deconstructed accordingly.
In the following code, the data passed to the function will checked against the patterns from top to bottom, and if the pattern is matched, its body will be used.
lottery :: (Integral a) => a -> String lottery 9 = "Jack pot!" lottery x = "Sorry, good luck next time!"
So here if you call lottery(5) you will get the message Sorry, good luck next time! because 5 is not matched to 9
Therefore, calling lottery(9) will give out the message Jack pot! because of matched pattern.
Note: If you define a function without catch-all pattern it will crash some time.
sayMyName :: Char -> String sayMyName 'a' = "Alfred" sayMyName 'b' = "Bob" sayMyName 'c' = "Chris"
So when you try to call sayMyName 'y' you will get error Non-exhaustive patterns because of the unexpected input.
By defining functions using separate patterns with their own bodies, programmer can write really tidy and readable code.
Lazy evaluation
Lazy evaluation is a method to evaluate a Haskell program. It means that expressions are not evaluated when they are bound to variables, but their evaluation is deferred until their results are needed by other computations. In consequence, arguments are not evaluated before they are passed to a function, but only when their values are actually used.
In simple term, an argument, inspite of being passed to a function, will not be evaluated until its result is needed in the function. More interestingly, a shared expression will not be evaluated more than once because its result is shared between places in which it is used.
For more of Haskell lazy evaluation check this link
List Comprehension
As you know that in Mathematics there is something called set comprehension which is quite similar to list comprehension.
A set comprehension looks like this:
A set of doubles of natural numbers which are less than or equal to 10.
This set can be expressed by using list comprehension
[x*2 | x <- [1..10]] [2,4,6,8,10,12,14,16,18,20]
Similar to set comprehension in Mathematics, isn't it?
Let's add condition to the list: tripple of the number is greater than or equal to 12
[x*2 | x <- [1..10], x*3 >= 12] [8,10,12,14,16,18,20]
More examples of list comprehension can be found here
Ruby
Support Functional programming
Ruby is an imperative language but we can still apply functional principles. It's the developer's choice to assure immutability of data.
For example:
Bad:
balances = {"LeBlanc" => 16000} balances["Yasuo"] = 20000 balances #=> {"LeBlanc"=>16000, "Yasuo"=>20000}
Good:
balances = {"LeBlanc" => 16000} all_balances = balances.merge("Yasuo" => 20000) #=> {"LeBlanc"=>16000, "Yasuo"=>20000}
Don't update, create a new one if you're following functional principles.
Ruby has built-in methods with functional approach and its destructive version. Look at the example of select and select!
numbers = [1, 2, 3 ,4] numbers.select { |num| num > 3 } numbers #=> [1, 2, 3, 4] numbers.select! { |num| num > 3 } numbers #=> [4]
Input should not be updated after executing a function. Again it's the programmer's choice to apply functional approach or not.
Everything is object
Either a piece of information is a string or an integer, that piece of information is an object. An object has its own properties and actions. In Ruby context, properties are instance variables and actions are methods.
For example: an integer can use times method
10.times { print "I am tired of writing this line 10 times " }
Observing the ancestors of an integer shows that an integer is a Fixnum and inherited from Object class
10.class #=> Fixnum 10.class.ancestors #=> [Fixnum, Integer, Numeric, Comparable, Object, Kernel, BasicObject]
The same goes for a string
"Hello World".class.ancestors #=> [String, Comparable, Object, Kernel, BasicObject]
Block
Closure can be attached to any method. A closure in this context is a block and what is a block?
A block is simply code that is inside do and end. There are two ways to write a block
- do and end code block
- { } inline code block
We can take an example of Array#select:
[1, 2, 6, 9, 69].select { |number| number > 5 } #=> [6, 9, 69] #or [1, 2, 6, 9, 69].select do |number| number > 5 end #=> [6, 9, 69]
|number| in this example is a block parameter and its value is each number in the array.
Blocks are inspired by functional languages. Matz said, “in Ruby closures, I wanted to respect the Lisp culture.”
Implicit return
In ruby, return is optional unless you want explicit return. The value of the last expression will be the return value of the method.
numbers = [1, 2, 3, 4] def collect_square numbers squares = [] numbers.each do |num| squares << num * num end squares end #=> not so good #Using functional approach and implicit return def collect_square numbers numbers.map { |num| num * num } end # Both examples will return [1, 4, 9 ,16]
One application of this feature is method chaining Let's say you have a Car and wants to perform multiple actions
class Car attr_accessor: position def initialize options = {} @position = 0 end def move_forward distance self.position += distance end def move_backward distance self.position -= distance end end
You want something like this: Car.new.move_forward(100).move_backward(50)
Simply return self at the end of move_forward and move_backward will do the magic
class Car ... def move_forward distance self.position += distance self end def move_backward distance self.position -= distance self end end
Everything is open
You can extend any classes and modules in Ruby, including built-in classes and mdoules. This makes everything open in Ruby.
For example you want to have something like 6.plus(11).minus(4)
module Fixnum def plus x self.+ x end def minus x self.- x end end 6.plus(11).minus(4) #=> 13
References
http://www.rubytips.org/2008/04/07/10-unique-ruby-language-features/ https://code.google.com/p/tokland/wiki/RubyFunctionalProgramming http://learnyouahaskell.com/syntax-in-functions