For me, lazy evaluation means on-demand computation and memorization, which happens to be called call-by-need.

I believe it is natural and useful in practice to implement black holes as exceptions rather than divergence.
I wish it is natural in theory, too.

And some programming in Idleness...

Racket

> (define a (letrec [(x (delay (force x)))] x))
> (define b (letrec [(x (delay (print "hi") (force x)))] x))
> (define c (letrec [(x (delay (print "hi") 0))] x))
> (force a)
force: reentrant promise
(force a)
force: reentrant promise
> (force b)
"hi"
force: reentrant promise
> (force b)
force: reentrant promise
> (force c)
"hi"
> (force c)
>

F#(1.9.7.8)

> let a:int Lazy = let rec x = lazy (x.Force ()) in x;;
> let b:int Lazy = let rec x = lazy (printfn "%s" "hi"; (x.Force ())) in x;;
> let c:int Lazy = let rec x = lazy (printfn "%s" "hi"; 0) in x;;
> a.Force ();;
System.InvalidOperationException: a lazy value was accessed during its own initialization
> b.Force ();;
hi
System.InvalidOperationException
> b.Force ();;
System.InvalidOperationException
> c.Force ();;
hi
> c.Force ();;
>

Haskell

I am not usually a Haskell programmer and am confused by that the interactive session and the batch compiled code behave differently as to exception vs nontermination behaviour. (Probably it has something to do with the interactive session attempting to Show.) Below is what I see from the compiled code.
import Control.Monad.Fix
main = do 
	x <- mfix (\x -> do print "hi" >> print (x::Int) >> return x)
	print "bye"
	print x
	print "bye"
	print x

"hi"
Exception:loop
import Control.Monad.Fix
main = do
	x <- mfix (\x -> do print "hi" >>  return (x::Int))
	print "bye"
	print x
	print "bye"
	print x
"hi"
"bye"
Exception:loop
import Control.Monad.Fix
main :: IO ()
main =  do 
	x <- (mfix (\x -> do print "hi" >>  return 1))
	print "bye"
	print x
	print "bye"
	print x
"hi"
"bye"
1
"bye"
1

OCaml

> let a = let rec x = lazy (force x) in x
> let b = let rec x = lazy (print_string "hi"; (force x)) in x
> let c = let rec x = lazy (print_string "hi"; 0) in x
> (force a)
Exception: Lazy.Undefined.
> (force a)
Exception: Lazy.Undefined.
> (force b)
hi
Exception: Lazy.Undefined.
> (force b)
Exception: Lazy.Undefined.
> (force c)
hi
> (force c)
> 

Scala

> lazy val b:int = {println("hi"); b}
hi
hi
hi
hi
hi
...
StackOverflowError

> lazy val c = {println("hi"); 1}
hi
> c
>

1.11.2010 (updated on 3.12.2010)