Lambda the Ultimate

inactiveTopic Why Functional Programming Matters
started 11/27/2003; 4:34:43 AM - last post 12/1/2003; 8:00:32 AM
Luke Gorrie - Why Functional Programming Matters  blueArrow
11/27/2003; 4:34:43 AM (reads: 11009, responses: 11)
Why Functional Programming Matters
by John Hughes (1984)

As software becomes more and more complex, it is more and more important to structure it well. Well-structured software is easy to write, easy to debug, and provides a collection of modules that can be re-used to reduce future programming costs. Conventional languages place conceptual limits on the way problems can be modularised. Functional languages push those limits back. In this paper we show that two features of functional languages in particular, higher-order functions and lazy evaluation, can contribute greatly to modularity.

This is a great paper because it's easy to read and it shows you why functional programming matters. It does this in the best of ways: by presenting beautiful programs. It's by far the best demonstration of lazy evaluation that I've found.

(I was really surprised to find that this paper hasn't been featured here before, though it has been linked several times.)

Posted to functional by Luke Gorrie on 11/27/03; 5:05:02 AM

Ehud Lamm - Re: Why Functional Programming Matters  blueArrow
11/27/2003; 1:21:29 PM (reads: 732, responses: 0)
Mea culpa. It's a must read.

Ehud Lamm - Re: Why Functional Programming Matters  blueArrow
11/28/2003; 3:59:17 AM (reads: 641, responses: 1)
the best demonstration of lazy evaluation

Lazy evaluation is indeed the star of the show presented, at least as presented in this paper.

But I must say that I am still unsure about lazy eval. It seems to me that supporting lazy constructs (like generators and streams) is a good idea, but that universal lazy evaluation, of the kind found in Haskell, is never going to be the default parameter passing style of major (mainstream) programming languages.

It makes reasoning about space complicated, and many find it confusing.

Thoughts, anyone?

Daniel Yokomiso - Re: Why Functional Programming Matters  blueArrow
11/28/2003; 6:55:43 AM (reads: 626, responses: 0)
IMO this paper provides a very strong case for generators/streams as a modularization mechanism. IIRC I don't think they provide good arguments for other forms of lazy evaluation.

As a side note, conflating streams with lazily-evaluated lists is, IMHO, a conceptual mistake, because their time and space properties are distinct. Also they merge finite and infinite data structures, making impossible (using the type system) to ensure that some function won't be called with infinite lists when it assumes (e.g. using a total fold) that just finite lists would be used.

It makes reasoning about space complicated, and many find it confusing.

Thoughts, anyone?

Lazy evaluation (as a default) also makes harder to program and write compilers, it's difficult to write (provably) strict code, because just adding a branch can make some expression non-strict again. AFAIK you need to either add strictness type annotations (Clean) or strictness code annotations (Haskell) to help the compiler. IMO this wouldn't happen if strict and lazy expressions used distinct syntax.

Luke Gorrie - Re: Why Functional Programming Matters  blueArrow
11/28/2003; 8:58:07 AM (reads: 608, responses: 0)
Off at a tangent, I was just reflecting on how cute some small pieces of code are when you first understand them. A few that I remember being especially delighted by are:

if True  x y = x
if False x y = y
 
(defmacro (let bindings . body)
  `((lambda ,(map car bindings) .,body)
    .,(map cadr bindings)))
 
(defmacro (let* bindings . body)
  (foldr (lambda ((var val) subexp)
           `((lambda (,var) ,subexp) ,val))
         `(begin .,body)
         bindings))

I've especially enjoyed seeing code like this really used to get languages off the ground, more than in lambda-calculus or denotational-semantics tutorials. (That's just me.)

I've just started reading the Haskell `Prelude.hs' from Hugs, which is really enjoyable too. Does anyone have references handy for some other similar code around the place in other styles? (Do e.g. Smalltalk and Forth systems get themselves "into the air" like this?)

Darius Bacon - Re: Why Functional Programming Matters  blueArrow
11/28/2003; 1:14:07 PM (reads: 584, responses: 0)
Smalltalk has a similarly high-level definition of if-then, with False and True as subclasses of Boolean. (Unfortunately, in Squeak at least, there's still magic -- e.g. you can't subclass Boolean yourself. I think Self is supposed to do this sort of thing better.)

DocOlczyk - Re: Why Functional Programming Matters  blueArrow
11/28/2003; 9:26:04 PM (reads: 528, responses: 1)
The paper is certainly useful for people who want to learn functional programming. And ten years ago when it was written, it may have made a case for functional programming. But at the present time every example in that paper can be handled much easier in an object-oriented language.

Ehud Lamm - Re: Why Functional Programming Matters  blueArrow
11/29/2003; 5:04:03 AM (reads: 499, responses: 0)
This a agood example why statements like "FP is better than OO" (or "OO is better than FP") are rarely helpful.

These languages offer a set of constructs, and even though they try to present a coherent and well integrated set of features, it is up to us to decide whether these features are also useufl separately, and for what purposes. Morever, language designers like all good artists steal ideas from one another whenever possible (think expcetions, think genericity, think VMs. The list goes on).

Natrually, the fact that lazy constructs such as streams and generators found the way into mainstream languages validates the point Hughes mad in his paper almost twenty years ago.

It is worth asking whether these features can be utilized to their full extent only in functional (or even pure) languages.

Patrick Logan - Re: Why Functional Programming Matters  blueArrow
11/30/2003; 9:18:38 PM (reads: 372, responses: 0)
In Smalltalk, True and False are subclasses of Boolean. The keyword message #ifTrue:ifFalse: is implemented by each subclass. The True subclass evaluates the true argument (a block of code). The False subclass evaluates the false argument. From memory since I don't have Smalltalk on this computer...

True>>ifTrue: trueBlock ifFalse: falseBlock
    ^trueBlock value

False>>ifTrue: trueBlock ifFalse: falseBlock ^falseBlock value

Patrick Logan - Re: Why Functional Programming Matters  blueArrow
11/30/2003; 9:47:32 PM (reads: 369, responses: 0)
It is worth asking whether these features can be utilized to their full extent only in functional (or even pure) languages.

Note that "objects" are not only a technique for organizing a program, but they are also a technique for delaying evaluation. The syntax is not always as tidy as in a lazy functional language, but as the program grows ever larger, this is less of an issue, especially with concise languages like Scheme, Smalltalk, or Python, for example.

Luke Gorrie - Re: Why Functional Programming Matters  blueArrow
12/1/2003; 1:34:37 AM (reads: 360, responses: 0)
But at the present time every example in that paper can be handled much easier in an object-oriented language.

This I have to see! Can you post some better code for one of the more significant examples, e.g. alpha-beta search? And which language(s) do you have in mind?

Frank Atanassow - Re: Why Functional Programming Matters  blueArrow
12/1/2003; 8:00:32 AM (reads: 332, responses: 0)
The True subclass evaluates the true argument (a block of code).

This is not quite a definition of if-then-else; if-then-else is not definable in an eager language. I think your Smalltalk definition is analagous to, in ML:

fun ifthenelse true ifbranch elsebranch = ifbranch ()
  | ifthenelse false ifbranch elsebranch = elsebranch ();

val example = ifthenelse true (fn () -> "true") (fn () -> "false")