Subject: Functional Programming to Become the State of the Art - ?

From: Shlomi Fish <[email-masked]>
Date: Mon, 11 Feb 2002 07:21:08 +0200 (IST)

As you may know some of the programming paradigms in use today, emerged
from the academia: Structured Programming, OOP, Patterns. There was a
gradual shift in the conception of programming from which to write code
that is as fast as possible to writing code that is maintainable as
possible. OOP, SP, patterns programming, etc. aim to make the code more
maintainable.

Now, modularity is a nice buzzword, but there are obviously guidelines to
making the code more modular. Such paradigms are not a panacea to having a
modular and maintainable code, but they usually help.

One paradigm that still did not gain global acceptance and recoginition
outside the academia is Functional Programming (or FP for short). Many
languages in use today are FP (Scheme, Perl), and some are even purely FP
(ML, Haskell). I believe following FP guidelines help make the code more
modular and maintainable, so I think it eventually will be considered an
elmentary programming paradigm such as OOP.

I don't see the masses of the programmers starting to write code in
Haskell; that's because I don't think FP means that assignment should be
eliminated altogether. Once OmerM told me that he had to do OOP in
Fortran. I asked him how it was possible and he told me that
"Object-oriented programming is a state of mind". FP is also a state of
mind, and FP or pseudo-FP techniques can be used in many languages
that do not directly support it.

( I believe that it is possible to write awful spaghetti code in C or
Pascal, while writing strictly Structured code in GW-Basic. And as Knuth
demonstrated, goto actually sometimes help in making a codebase more
structured)

Now for some examples and use cases:

1. Pointers to functions in C are a pseudo-FP element. Many C++
programmers tend to overlook their importance, and think that one should
inherit a class, in order to create a callback. While callbacks as
pointers to functions or as derived classes are interchangeable,
_thinking_ about them as functions is important.

In Freecell Solver for example, I wrote several test functions, each
performing a different type of moves. The user could choose the order in
which those tests were performed. Furthermore, several scans were written,
each one using the tests differently.

2. It is obvious that coding a map, filter, accumulator, etc -like
functions in C would have a large amount of overhead. However, one
could possibly use code generators that abstract such steps into
combined loops based on a template. I don't remember if the UML standard
gives way to doing it, but I think it should. It is possible that one can
read (say) Scheme or Perl code and compile it into an optimized C code.
(or does Forth supports such constructs?)

3. Passing a void * context variable to a function emulates a closure in a
way. I believe that by having an void * upper_context pointer there, one
can have a certain lexical scoping-feel to the code. I.e:

void myfunc(int , void * h)
{
	h = (mystruct *)h
	.
	.
	.
	new_context = malloc(sizeof(mynewstruct));
	new_context->up_context = h;
	/* Fill new_context with other stuff */

	newfunc(.... , new_context);
}

(can anybody point me to an LC code in C++ or in C, that way?)

4. Recursion - obviously an FP methodology, which is now a very common
practice.

And it goes on. Naturally, some languages support FP much better than
other languages. I can easily write FP code in Perl, but will have a hard
time writing it in COBOL. (it's not impossible to write it there, just
very hard)

This is my impression of what will happen. I cannot guarantee that it will
happen anytime soon, because prophecy was taken from the prophets and
given to fools. However, I believe knowledge and experience in FP can help
someone produce better code. (refer to SICP) And naturally, many
techniques that originated in the functional world, can be applied this
way or another in real-world apps.

Regards,

	Shlomi Fish

----------------------------------------------------------------------
Shlomi Fish        [email-masked]
Home Page:         http://t2.technion.ac.il/~shlomif/
Home E-mail:       [email-masked]

"Let's suppose you have a table with 2^n cups..."
"Wait a second - is n a natural number?"

---

From: Adi Stav <[email-masked]>
Date: Mon, 11 Feb 2002 15:10:04 +0200

> void myfunc(int , void * h)

This is a no-op. A (void*) will always remain a (void*). Remember than 
in C, unlike in C++, type is not a runtime quality.

> 	new_context->up_context = h;

Even if up_context is a pointer to a struct, this assignment is legal,
and even without your earlier attempt to assign type information to h.
It is a common mistake to always cast (void*) into (struct foo*), while 
in fact ANSI C guarantees a correct automatic conversion from (void*)
to a pointer to any data type and back. Note that this automatic (void*) 
conversion feature supports your point -- it shows that having a 
reliable and convenient way to pass generic context around was deemed
such an important feature by the ANSI C designers that it got into the
design of an otherwise very conservative and simple language.