For-each and map in Scheme
Asked Answered
C

2

8

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.

Chant answered 15/12, 2014 at 0:23 Comment(0)
G
13

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.

Gans answered 15/12, 2014 at 0:46 Comment(0)
E
5

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

Educator answered 15/12, 2014 at 0:30 Comment(2)
In non-Racket Scheme, are there side effects? What does for-each do in MIT-Scheme?Shaunta
@SeanLetendre As I understand it, the explicit point of for-each is the side effects - that's why the order is guaranteed. It's the same in all Schemes.Foremast

© 2022 - 2024 — McMap. All rights reserved.