Catch up on stories from the past week (and beyond) at the Slashdot story archive


Forgot your password?
DEAL: For $25 - Add A Second Phone Number To Your Smartphone for life! Use promo code SLASHDOT25. Also, Slashdot's Facebook page has a chat bot now. Message it for stories and more. Check out the new SourceForge HTML5 Internet speed test! ×

Comment Re:Why "lazy"? (Score 1) 439

This function is just as "lazy" in that until the call to it, nothing is calculated, and only the minimum required work is done.

You're missing the point entirely.

The definition of a strict function is one where

f _|_ = _|_

Where the funny "_|_" symbol means "bottom," i.e. the system might diverge, error unrecoverably or do any number of things, but these are things you generally don't want to happen.

In most languages you are used to functions for example, evaluating their parameters "inside out," meaning in a call like

f (g x) (h y)


f x y = x + y

You first evaluate 'g x', then 'h y' and finally you evaluate 'f' with the results of those two evaluations. In contrast with a lazy language, functions evaluate "outside in" meaning that in the above call, you immediately call f and in the body of f, we only evaluate the 'x' and 'y' parameters if their value is forced, i.e. its concrete representation is needed (for example being printed.)

In haskell functions are not only lazy, all values are lazy by default. The result of a function is lazy, any regular computation is lazy. But what does this buy us?

It gets us a cleaner separation of concerns and laziness buys you modularity, basically.

Take for example the completely contrived function:

tenEvenNums = take 10 (filter even [1..])

The important thing here is that with laziness, the generation of the infinite list of 1 to infinity is separated from the consumption of the list by functions take, filter and even (take takes n elements from a list, even returns true/false if a number is even/odd, and filter takes a list and returns a new list based on a predicate.) The entire definition is just built up from a few compositions and nothing else.

Laziness gives us a powerful glue to compose functions and re-use them. Contrast this with the C version of the same thing:

int tenEvenNums(int *arr) {
    int i;
    int j;

    for(i = 1, j = 0; j < 10; i++)
        if(i % 2 == 0)
            arr[j++] = i;

    return 0;

Note there is no longer as clean a separation of concerns - we must consume and prune the values at the same time we generate them. This isn't as good for modularity because we can't as easily abstract out the more common parts like we can when we're lazy - it wouldn't be possible in this instance to have one function which generates the infinite list; C is strict, so it'd just be an infinite loop.

Like I said this example is extremely contrived but it conveys the point that when you're lazy it's a whole lot easier to build functions out of smaller, more general functions (generality has a bit to do with the type system, however.) When dealing with larger blocks of code this can be more and more important, because if you're lazy (and by association also pure since laziness and impurity don't at all mix in any way,) it's a whole lot easier to glue functions together rather than repeating common things so much.

I recommend you go read "Why Functional Programming Matters" by Hughs for a more in-depth treatment, and it also covers HOFs which are also quite great.

Slashdot Top Deals

A list is only as strong as its weakest link. -- Don Knuth