Functional Programming for Imperative Programmers

This article only covers basic characteristics which separate out Functional languages from Imperative languages. All of following concepts are applicable on all functional languages. After this, select one language and read related tutorial.

We are living in a Matrix, Matrix of Imperative world. e.g. if I ask you write a program to print 1 to 10, the program will be:

for (int i=1; i<=10 ;i++) {
    printf("%d\n", i);
}

In the Matrix of functional programming, there are no for/while loop. Then, how we shall print such numbers? Following is an example in ‘elixir’:

Enum.map(1..10, fn(x) -> IO.puts x end)

yes, that’s it. Few functional languages (like ocaml/F#) provide ‘for’ loop which is nothing but synthetic sugar to provide similar functionality, but they do not support complete functionality of a for loop like break, continue.

So, while reading this article, try to understand a completely different world from a completely different perspective. You are going from one Matrix to another Matrix. Remember, there is no real world.

Characteristics of Functional Programming

Purity

Pure code is something which is neither effected by external world nor effects external world. In other word, a function is pure if it provides same output for same set of inputs. e.g.

int sum(int a, int b) {
    return (a+b);
}

now, whatever happens in world, let USA attack Russia, let there be some earth quack, for  a=3 and b=4, the output of function sum will always remain 7. Now lets check another example:

int c = 0;
int sum_avg(int a, int b) {
    if(c == 0)
        return (a + b);
    return (a + b)/2;
}

int main_func () {
    int sum = sum_avg(3, 4);
    c = 1;
    int avg = sum_avg(3, 4);
}

Can you predict output of sum_avg function? No. It depends on the value of ‘c’ variable, which is global and can be modified anytime. The function sum_avg will return different values for same set of inputs, so sum_avg function is not pure. If I write sum_avg again as

int sum_avg(int a, int b, int c) {
    if(c == 0)
        return (a + b);
    return (a + b)/2;
}

int main_func () {
    int sum = sum_avg(3, 4, 0);
    int avg = sum_avg(3, 4, 1);
}

After this changes, function sum_avg is a pure function. For same set of input, output will always remain same.

The major advantage of Purity is better support for concurrency. Since a pure function does not have any dependency on any external data/function, it can be run in parallel.

Immutability

Now, imagine a function in which you can not modify any variable? Seems funny/impossible/useless? But this is the core of a functional programming language.

Functional programming languages do not support Mutable data structures and this sentence is pure lie. The correct sentence will be Functional programming languages do not encourage use of Mutable data structure.

How it is done? I have one list in which I need to add another element, but list is immutable. Lets see it in Haskell:

addElement a lst = a : lst 

lst = [1,2,3,4,5]
lst1 = addElement 0 lst 

lst1
[0,1,2,3,4,5] 

Function addElement is used to append a element to a list in beginning.  We have one list lst. It is not possible to mutate this list, but if you want to add a element, call addElement function and store the result in lst1. lst and lst1 represent two independent lists in memory, so no mutation of any variable and yet you have a list which you wanted.

Recursion

As we already discussed, functional languages do not support loops, then how do they perform repetitive task? Try to remember school days, where in initial classes teachers discussed about ‘Recursion’, and then we read somewhere ‘Recursion’ is not good and should not be used. Here Recursion is good and god.

e.g. create a list of 1 to 10 of even numbers.

generateList _ 0 = []
generateList i j = if even i then i : generateList (i+1) (j-1)
                             else generateList (i+1) (j-1)

There are other simple way to do it, but for now lets stick to this version. We wrote a function generateList, which takes two parameters – i (start) and j (end);

Wait, variable with name i and j. This is really not a good practice, right? Not in imperative languages, where functions are lengthy and at some point, you might have to go back to definition to find out what i and j are taken for. In case of functional programming, functions are small and concise. So, taking variables with name i, j, x, y are pretty common.

If i is even, append i and call generateList function again with i+1 and j-1. If j becomes 0, return an empty list.

Output of above program:

generateList 1 10
[2,4,6,8,10]

Tail Call Optimization: TCO is the reason why recursion is not considered evil in functional programming. When a function recursively calls itself, and there is no need to wait for its return, the stack will be replaced. The above answer is not Tail Call optimized, because we are waiting for return value of generateList, so that we can append i.  Remember, just like imperative languages, function language will cause stack overflow with large iteration during recursion, if not TCO optimized.

Here is TCO version of same program.

generateList' _ 0 x = x
generateList' i j x = if even i then generateList' (i+1) (j-1) (i:x)
                                else generateList' (i+1) (j-1) x

Higher Order Functions and Closure support

Higher-order functions are functions that take other functions as their arguments. Ok, so what?

We have some good functions provided by functional languages mainly map, fold, filter. These are your savior from recursion. How? Lets see.

map: map takes one function as a parameter and execute it on each member of list and returns a new list. e.g., lets double each element of a list.

a = [1,2,3,4,5]
dblMe = map (doubleElement) a

doubleElement x = 2 * x

Output:

dblMe
[2,4,6,8,10]

So, map is higher order function. Now, lets modify doubleElement and pass a closure instead a complete function.

a = [1,2,3,4,5]
dblMe = map (\ x -> 2 * x) a

Normally all functional languages support Closures.

fold: Fold also takes a function as parameter, a initial value and executes it on each element of list and returns a folded value. e.g Sum of all elements of list.

foldMe = foldl (\ acc x -> acc + x) 0 a

Output:

a = [1,2,3,4,5]
foldMe
15

Fold takes each element from list ‘a’ and pass it to closure. Closure add it to acc, which is initialized with 0. Finally sum of all elements is returned.

filter: Filter also takes a function as parameter (but this function returns Bool value) and executes it on each element of list. If passed function returns True, filter appends element in return list. e.g lets write previous program which generates a list of even numbers in Elixir.

1..10 |> Enum.filter(fn x -> rem(x, 2) == 0 end)

Comments and Bugs are invited.

Simple UDP Client/Server in golang

Being a new language, the example codes are not easily available for Golang. For other languages like Java and C, just put a keyword in Google, you will find a lot examples for it. Same is not true for golang.

I faced the same issue for UDP Client and Server code. Finally I managed to code with help of few available examples.

First set the PATH for go by using following command.

export PATH=/path/to/go/bin:$PATH

Here is the code for the same.

Server: server.go

package main

import (
    "fmt"
    "net"
    "os"
)

/* A Simple function to verify error */
func CheckError(err error) {
    if err  != nil {
        fmt.Println("Error: " , err)
        os.Exit(0)
    }
}

func main() {
    /* Lets prepare a address at any address at port 10001*/    
    ServerAddr,err := net.ResolveUDPAddr("udp",":10001")
    CheckError(err)

    /* Now listen at selected port */
    ServerConn, err := net.ListenUDP("udp", ServerAddr)
    CheckError(err)
    defer ServerConn.Close()

    buf := make([]byte, 1024)

    for {
        n,addr,err := ServerConn.ReadFromUDP(buf)
        fmt.Println("Received ",string(buf[0:n]), " from ",addr)

        if err != nil {
            fmt.Println("Error: ",err)
        } 
    }
}

Run this file with following command

go run server.go

Client: client.go

package main

import (
	"fmt"
	"net"
	"time"
	"strconv"
)

func CheckError(err error) {
	if err  != nil {
		fmt.Println("Error: " , err)
	}
}

func main() {
	ServerAddr,err := net.ResolveUDPAddr("udp","127.0.0.1:10001")
	CheckError(err)

	LocalAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
	CheckError(err)

	Conn, err := net.DialUDP("udp", LocalAddr, ServerAddr)
	CheckError(err)

	defer Conn.Close()
	i := 0
	for {
		msg := strconv.Itoa(i)
		i++
		buf := []byte(msg)
		_,err := Conn.Write(buf)
		if err != nil {
			fmt.Println(msg, err)
		}
		time.Sleep(time.Second * 1)
	}
}

Run this file with following command in another terminal

go run client.go

Kernel panic while using wireless (wifi) drivers of Mediatek 7601U chipset

After my experience with HP and theirs support team, I became much frustrated (Read it at http://wp.me/43Iof). Now I had few options left:

  • Throw this garbage (HP Pavilion 15) to bin.
  • Sell it on olx.
  • Spend few more bucks and buy a wireless USB adapter.

Since, I found that a bug is opened for Mediatek 7630 PCIe card on launchpad, I assumed that the fix should be available with in few months. I dropped my idea of throwing it up. (Obviously, first two options were a ridiculous thought.)

Third option seems to be feasible. I bought ‘Leoxsys Nano Wireless N USB WiFi Adapter LEO-NANO150N’, which is based on Mediatek 7601U chipset (Actually, it was the cheapest one available on Internet. :D). I confirmed that drivers for Linux for the same chipset are available in market.

At that time, I was using Ubuntu 13.04 – 64 bit. I copy the driver (v 3.0.3) from provided CD, compiled and loaded the module. Nothing happened. Right, you heard me correct, nothing happened. Network Manager could not detect any wifi adapter. I installed wicd, and bla bla, but nothing worked.

After few days wasting, I found that you have to set following parameters in config.mk file.

‘HAS_WPA_SUPPLICANT=y’
‘HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y’

I dont know, why they did not set them by default. Whatever. I downloaded latest driver (v3.0.4) from Mediatek site, compiled and as soon as I inserted module, my wifi connection was alive. This is the first time, when my notebook was experiencing WIFI. If my notebook could have dance, it would have been dancing like Shakir. I had tears in my eyes due to happiness. lol…..

Soon after, I start downloading few required software. Within 5 minutes, kabooooooooooooooooooooooooooooooooooooom…. a black screen was displayed on screen. Everything was over. My notebook was feeling like Justin Bieber, completely screwed. I didn’t lost my whole faith in humanity. After hard boot, everything was working fine. Then after few minutes, system froze. Nothing was responding.

After, a lot of search, I found that the drives which Mediatek is providing is for 32 bit system. In 64 bit system, there are lot of changes required in 32 bit driver e.g. in 64 bit system, skb->tail is a pointer, in 32 bit system, it rather is an offset to add to skb->data to obtain the pointer.  The details description is provided at:

http://pastebin.com/VkUjULJ5

I discussed the same with Mediatek team and they agreed that this is the reason of Kernel Panic.

Following is the mail communication received from Mediatek team;

“Great thanks for your detail information. It really a issue of the 64-bit system.  Did you try patches described in these websites? If so, did the kernel still crash?”

The above answered was received on 28-Oct-2013. Since then, I have not listen from the team. Neither there is any new version uploaded on Mediatek site.

I have now shifted to Mint 15 – 32 bit system. Now everything is working fine. My life just became hell  due to HP and Mediatek. Now, I am able to run wifi with USB dongle. Neither HP nor Mediatek has provided any drivers for 7630 card till now (28-Nov-13). In fact Mediatek has not provided a single reply for all the mails sent for 7630 card.

I hope soon I will be using inbuilt wifi card. With this hope, I finish this post here.

A frustrated customer of HP Pavilion 15 (Ubuntu) Notebook

Last month, I purchased HP Pavilion 15 series Notebook with Ubuntu pre-installed. I assumed that if HP is selling a notebook with Linux pre-installed, all the components should be Linux compatible. What a big mistake, I made!!

As soon as I reached home, I installed Ubuntu 13.04 without any thought. I noticed that wireless adapter was not detected at all. After few hours of googling, I found that my notebook is using Mediatek 7630 wireles adapter, for which there is no drivers are available. I was shocked!!

I tried to contact HP and they clearly said “HP does not provide support for Linux.” What a joke!! Then, why do you sell notebook Linux pre-installed? Let the customer identify about the Linux compatibility for each part himself. You could have mentioned about the drivers availability before selling. Dear HP, may be this fact can bring you in shock, but every user does not buy your laptop to install Windows at home.

I couldn’t understand one point. When you are delivering a notebook with wireless drivers available, means you have received that from vendor. Then, why cant you make them available to user? or you can also asked vendor to make drivers available on their site.

One more point, why did you choose such vendor, while a lot of better vendors are available? Did you get some bribe? Oh! you cant tell me your business strategy. This can be your excuse for now.

I thought may be vendor Mediatek can help me. Till now, I have dropped around 4-5 mails, but seems like they dont care at all. After all, I am not their’s customer. I am the customer of HP. Then how does I matter to Mediatek. Right Mediatek??  

Lesson Learned: May be, you have a lot of trust in any brand, they will not bother. They will take just few minutes to break you trust.

If anyone from HP or Mediatek is reading it, I know you wont bother a bit. So, you wasted a lot of time here. You could have made few more customers frustrated in this period. I am sorry for it.