His argument is that concepts such as laziness lead to unexpected results in imperative languages. However, such problems also occur in pure functional languages:
I would like to point out that there are classes of laziness. Haskell's laziness guarantees that an expression will not be evaluated if it is not used. e.g. take_first(42, 42/0) will not return an error. This enables you to construct infinite lists of primes and such.
Some classes of functional languages had lenient evaluation, evaluation is still lazy, but all expressions will be evaluated at some point in the program. You cannot do the infinity tricks, but you can still write the nice recursive functions, those that are used to show off the benefit of laziness.
The Haskell type of laziness bites you in the ass when trying to do parallel evaluation, which is why you need the rpar/rseq constructs to avoid opening the nasty trapdoors that regular evaluation will not hit.
Even besides I/O and parallelism the laziness can bite you. Mainly, it can make it hard to predict memory/processing use, unless you are intimately acquainted with the innards of Haskell.
Some classes of functional languages had lenient evaluation, evaluation is still lazy, but all expressions will be evaluated at some point in the program. You cannot do the infinity tricks, but you can still write the nice recursive functions, those that are used to show off the benefit of laziness.
The Haskell type of laziness bites you in the ass when trying to do parallel evaluation, which is why you need the rpar/rseq constructs to avoid opening the nasty trapdoors that regular evaluation will not hit.
Even besides I/O and parallelism the laziness can bite you. Mainly, it can make it hard to predict memory/processing use, unless you are intimately acquainted with the innards of Haskell.