2014-12-15 2 views
3

스키마에서이 두 함수의 차이점은 무엇입니까? Dr Racket R5RS 언어를 사용하여 시뮬레이터 게임을 만들었으며 어떤 것이 더 나은지 결정할 수 없었습니다.Scheme에 대한 각각 및 맵

답변

2

큰 차이가 있습니다. map은 목록의 요소에 주어진 절차를 적용한 결과가 포함 된 목록을 반환하고 for-each은 void를 반환합니다. 당신이 계산의 결과를 필요로하고 그 절차의 부작용에 관심이 때 for-each을 사용할 때마다

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

당신은 map 사용합니다.

두 번째 중요한 차이점은 for-each이 주어진 절차가 요소에 순서대로 적용된다는 것입니다. map의 경우, 반환 된 목록은 원래 목록 [s]의 순서를 따르지 만 호출이 순서대로 이루어 졌다고 보장 할 수는 없습니다.

here

+0

비 -Lacket 체계에서 부작용이 있습니까? MIT-Scheme에서'for-each'는 무엇을합니까? – SeanLetendre

+0

@SeanLetendre 제가 이해하고 있듯이 for-each의 명백한 요지는 부작용입니다. 그것이 주문이 보장되는 이유입니다. 그것은 모든 계획안에서 동일합니다. –

4

for-each는 왼쪽에서 오른쪽 목록 요소에 지정된 함수를 평가하고,이 함수의 리턴 값을 폐기한다. 그것은 목록의 각 요소에 부작용을주기에 이상적입니다.

map은 특정 순서없이 목록 요소에 대해 지정된 함수를 평가합니다 (대부분의 구현에서는 오른쪽에서 왼쪽 또는 왼쪽에서 오른쪽으로 사용하지만). 함수의 반환 값을 저장하여 호출자에게 반환합니다. . 목록의 각 요소에 대해 순수 기능 처리를 수행하는 데 이상적입니다.

map의 반환 값이 사용되지 않으면 대신 for-each을 사용하는 것이 좋습니다. 그런 식으로 함수 호출에서 반환 값을 수집하는 것을 번거롭게 할 필요가 없습니다.

은 (제외 : Clojure의에서는 map의 리턴 값이 소정의 기능은 실현되는 요소 호출 수단 지연 시퀀스이다.)


기술적 구현 세부.

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

정말 간단하고, 보장은 왼쪽에서 오른쪽 순서 : for-each의 단순화 한 목록 버전은 일반적으로 다음과 같이 구현됩니다. map 단순화 한 버전리스트와 대조 :

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

, 함수의 인수에 대한 평가 순서는 특정되지 않는다. 따라서 (foo (bar) (baz) (qux))과 같은 표현 인 경우 bar, bazqux에 대한 호출은 임의의 순서로 발생할 수 있지만 foo이 호출되기 전에 모두 완료됩니다.

이 경우 (func (car rest))이 먼저 발생하거나 (recur (cdr rest)) 이후에 발생할 수 있습니다. 어느 쪽이든 보장 할 수는 없습니다. 그렇기 때문에 사람들은 map이 평가 주문을 보증하지 않는다고 말합니다.