A poke at the essence of functional programming
I used to work for IBM on the Java implementation. I learned the language inside-out. I did all those Sun certifications and other spanky things. I wanted to understand what a lot of people alleged was so special. I didn’t ever find it.
I have found that few people can tell me the answer to this question. If you don’t know the answer, don’t fret; it’s not the important part.
method(s1.charAt(i), s2.charAt(j));
Assuming
s1ands2are both of the typejava.lang.String, then which call tocharAtwill occur first?
Many people would correctly guess at the left-most one. This is correct and is mandated by the specification.
However, on introspection, the reason nobody really knows is because it doesn’t matter. If the specification implementation had a bug and executed the right-most call first, then we, the programmer, would never even know. We gloss over this every day when we read Java code.
However, does this hold for all functions? What if it was something other than charAt? No, unfortunately, this only holds true for a specific set of functions. The charAt function is referentially transparent. For any given String and any given int then charAt will consistently return the same char. This is true for other referentially transparent functions too, but not any arbitrary function. Imagine if charAt did a database call or something like that!
Let us suppose now a new language feature that enforced the referential transparency of our functions. If it is referentially transparent, the compiler makes sure of it. Now imagine a new language where every function was referentially transparent.
All of a sudden, in the blink of an imagined hypothetical, the explicit order of invocation is no longer important. Just like that, poof, gone.
Welcome to the beginning of an understanding of the essence of functional programming.
Have fun! ![]()
March 25th, 2010 at 6:47 pm
Well as the new trends advice using a noSQL databases like CouchDB and MongoDB, that’s the reason to go back to functional programming as well. As they use to say, every new trend is a forgotten old one.
Don’t forget the hybrid languages such as Groovy. At some point we might return to Assembler or some other older code standard just based on the spiral way of thinking.
March 25th, 2010 at 8:05 pm
lol, excellent article, well done. that’s a great explanation!
March 26th, 2010 at 12:53 am
Heh. I said the order would be indeterminate, but I didn’t know the spec mandated that the leftmost method be called first.
Apparently I already understood the methods to be referentially transparent. If they weren’t, then I would have to be more careful about how to call them. I.e., if the second method call were to have an effect on one the objects involved in the first method call, I would hope the programmer knew about such a possibility and took steps to make the order explicit. E.g., by separating the method calls out into individual statements.
Not very good if you want to avoid being verbose, but nice if you want your code to be self-documenting and if you want to be crystal clear about what you’re attempting to do.
By enforcing referential transparency, I suppose you accomplish just that. Not bad.
March 26th, 2010 at 8:35 pm
All functions are referentially transparent … sounds cool. It does have a few problems though :
you can’t write to the screen in that language
you can’t update a database in that language
more general, you cannot EVER update any external state
So the whole house of cards falls down. You allow updates to the screen, violating the functional language spec. You allow database updates somehow, again violating the language.
And there is always the next thing that doesn’t work in a functional way. Whoops. Pretty soon you’re back at java, and referentially transparent functions are exceptions.
To stop people whining one implements the “const” keyword in the language, which, admittedly, does allow for some nice optimizations you couldn’t otherwise do (although there is more than enough work to allow for automatic recognition of constness, I must admit that enforcing constness is a nice feature to have)
Of course, then your language is “too complex”. Heh.
March 26th, 2010 at 9:33 pm
Hello oelewapperke,
What you have said is false. You can write to the screen in that language and you can also update the database. More generally, you certainly can update external state. The “house of cards” certainly does not fall down. After some realisation, pretty soon you’re no longer using impractical languages such as Java, which incidentally, is specified with 50 operators that are all pure as are all compiler-aware functions.
You might want to look at pure functional languages. Specifically, those that are turing-complete, since this will invalidate your claim. To give even more strength to this fact, observe that the pure lambda calculus is turing-complete. I recommend some reading by Wadler, Moggi or Hughes to get you started.
Woops indeed
March 27th, 2010 at 7:02 pm
Cool idea. Agree, in most cases you need only referentially transparent functions.
And even if somebody will argue, that it’s not acceptable to have only them in mainstream languages, some sort of “procecure” semantic could be added.
March 27th, 2010 at 9:17 pm
Andrey, there are no mainstream languages that do not already have them, almost exclusively.