Just to roil the waters a bit: no programming language can ever hope to
be "purely functional", for the simple reason that real computation (i.e.
computation involving IO, interactivity) cannot be functional. "Functional
programming" is an unfortunate misnomer. On the other hand, languages can
be algebraic. The whole point is provability, not
function-ness.
More generally: judging by the many competing
proposals addressing the issue of how to think formally about real computation
(just google stuff like hypercomputation, interactive computation, etc.;
Jack
Copeland has lots of interesting stuff on this) is still an open
question. Soare has
three essential
papers on the subject. I guess the moral of the story is that the
concepts and the terminology are both still unstable, so lots of terms in common
use are rather ill-defined and misleading (e.g. functional
programming).
Lazyness is just a matter of how one attaches an actual
computation to an _expression_; a better term would be something like "delayed
evaluation" or "just-in-time computation". You don't have to work through
any logic to have laziness. Just think about how one reads a mathematical
text - you need not actually compute subformulae or even analyze them logically
in order to work with them. This applies right down to expressions like
"2+3" - one probably would compute "5" on reading that, but what about
"12324/8353"? You'd leave the computation until you absolutely had to do
it - i.e. one would probably try to eliminate it algebraically
first.
-gregg