Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For-each and map in Scheme

Are there any difference between these 2 functions in scheme?I am using Dr Racket R5RS language to make a simulator game and I could not decide which one is better.

like image 324
Prethia Avatar asked Dec 15 '14 00:12

Prethia


2 Answers

for-each evaluates the given function on the list elements left-to-right, and discards the return value of the function. It's ideal for doing side-effecting things to each element of the list.

map evaluates the given function on the list elements in no specific order (though most implementations will use either right-to-left or left-to-right), and saves the return value of the function to return to the caller. It's ideal for doing pure-functional processing on each element of the list.

If the return value of map is not going to get used, it is better to use for-each instead. That way, it doesn't have to bother collecting the return values from the function calls.

(Aside: in Clojure, the return value of map is a lazy sequence, which means the given function is only invoked for the elements being materialised.)


Technical implementation details. A simplified one-list version of for-each is usually implemented like this:

(define (for-each func lst)
  (let loop ((rest lst))
    (unless (null? rest)
      (func (car rest))
      (loop (cdr rest)))))

Really straightforward, and guarantees left-to-right order. Contrast with a simplified one-list version of map:

(define (map func lst)
  (let recur ((rest lst))
    (if (null? rest)
        '()
        (cons (func (car rest)) (recur (cdr rest))))))

In Scheme, the evaluation order for function arguments is not specified. So for an expression like (foo (bar) (baz) (qux)), the calls to bar, baz, and qux can occur in any order, but they will all complete before foo is called.

In this case, the (func (car rest)) can happen first, or it may happen after (recur (cdr rest)). It's not guaranteed either way. This is why people say that map does not guarantee an evaluation order.

like image 153
Chris Jester-Young Avatar answered Nov 07 '22 08:11

Chris Jester-Young


There is a big difference: map returns the list containing the results of applying the given procedure on the elements of the list (or lists), while for-each returns void.

> (for-each (λ (x) (add1 x)) '(1 2 3))
> (map (λ (x) (add1 x)) '(1 2 3))
'(2 3 4)

You use map whenever you need the result of the computation and you use for-each when you're interested in the side effects of that procedure.

The second important difference is that for-each guarantees you that the given procedure is applied on the elements in order. For map, although the list returned respects the order of the original list[s], it is not guaranteed that the calls were made in order.

more here

like image 23
Tudor Berariu Avatar answered Nov 07 '22 08:11

Tudor Berariu