Map 对于每个和映射到方案

Map 对于每个和映射到方案,map,foreach,scheme,racket,Map,Foreach,Scheme,Racket,scheme中的这两个函数有什么不同吗?我正在使用Dr Racket R5RS语言制作一个模拟游戏,我无法决定哪一个更好。有很大的不同:map返回列表,其中包含对列表元素应用给定过程的结果,而每个的返回void > (for-each (λ (x) (add1 x)) '(1 2 3)) > (map (λ (x) (add1 x)) '(1 2 3)) '(2 3 4) 只要需要计算结果,就可以使用map,如果您对该过程的副作用感兴趣,就可以对每个使用 第二个重要的区别是,for

scheme中的这两个函数有什么不同吗?我正在使用Dr Racket R5RS语言制作一个模拟游戏,我无法决定哪一个更好。

有很大的不同:
map
返回列表,其中包含对列表元素应用给定过程的结果,而每个的
返回void

> (for-each (λ (x) (add1 x)) '(1 2 3))
> (map (λ (x) (add1 x)) '(1 2 3))
'(2 3 4)
只要需要计算结果,就可以使用
map
,如果您对该过程的副作用感兴趣,就可以对每个
使用

第二个重要的区别是,
for each
保证给定的过程按顺序应用于元素。对于
map
,虽然返回的列表尊重原始列表的顺序,但不能保证调用是按顺序进行的


更多

对于每个
从左到右计算列表元素上的给定函数,并丢弃函数的返回值。它非常适合于对列表中的每个元素执行副作用的操作

map
对列表元素上的给定函数不按特定顺序求值(尽管大多数实现将使用从右向左或从左向右),并保存函数的返回值以返回给调用方。它非常适合对列表中的每个元素进行纯函数处理

如果不使用
map
的返回值,最好对每个
使用
。这样,它就不必费心从函数调用中收集返回值

(旁白:在Clojure中,
map
的返回值是一个延迟序列,这意味着给定的函数只针对被具体化的元素调用。)


技术实施细节。每个
的简化单列表版本通常是这样实现的:

(define (for-each func lst)
  (let loop ((rest lst))
    (unless (null? rest)
      (func (car rest))
      (loop (cdr rest)))))
非常简单,并保证从左到右的顺序。与简化的单列表版本的
地图相比

(define (map func lst)
  (let recur ((rest lst))
    (if (null? rest)
        '()
        (cons (func (car rest)) (recur (cdr rest))))))
在Scheme中,未指定函数参数的求值顺序。因此,对于像
(foo(bar)(baz)(qux))
这样的表达式,对
bar
baz
qux
的调用可以以任何顺序发生,但它们都将在调用
foo
之前完成


在这种情况下,可以先执行
(func(car rest))
,也可以在
(recur(cdr rest))
之后执行。这两种方式都不能保证。这就是为什么人们说
map
不能保证评估顺序。

在非敲诈方案中,是否有副作用?在麻省理工学院的方案中,
对每个
都有什么作用?@SeanLetendre据我所知,
对每个
的明确意义在于副作用——这就是为什么顺序是有保证的。所有的方案都是一样的。