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