Comment

Comment by IvoDankolov

Actually, what you have written is not foldl, it's foldr. Why is it going right to left? Let's expand your example:

    (foldl * 1 '(1 2 3))
    (* 1 (foldl * 1 '(2 3))
    (* 1 (* 2 (foldl * 1 '(3))))
    (* 1 (* 2 (* 3 (foldl 1 '()))))
    (* 1 (* 2 (* 3 1)))
    ...
    6
Basically, the calls to * start nesting into each other, so the one that actually gets evaluated first is the rightmost one.

What would actually be foldl is this:

    (define (foldl fn accum lst)
       (if (null? lst)
            accum
            (foldl (fn accum (car lst)) (cdr lst))
       )
    )
Now if you expand this (dropping the tail recursion):

    (foldl * 1 '(1 2 3))
    (foldl * 1 '(2 3))
    (foldl * 2 '(3))
    (foldl * 6 '())
    6
And even though you think that such a tiny thing can't be a good implementations, it actually is super efficient. The tail recursion is automatically optimized for you (and you can assume that for any functional language - it's a very crucial optimization for this style of code, after all). That's what the core of it will be in an actual implementation, though with added error handling, type checking and so on.

P.S. unlike haskell, in Racket you don't really need to fold the basic operators, they take variable arguments, so you can just:

    (apply * (list 1 2 3))
in order to get it to run on a list.
parent IvoDankolov 14 years ago

No comments yet

Be the first to share your thoughts.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton