map 사용하기

map 함수는 하나의 변환 규칙을 리스트 전체에 적용합니다. 루프 없이 데이터를 일관되게 다루는 방법을 배워 보세요.

이전 문서입니다. 리스트의 요소를 고르고 바꾸려면 현재 map, filter, fold, apply 사용하기 실습을 따라 하세요.

리스펙스에서는 데이터 리스트를 다루는 일이 잦습니다. 전통적인 루프를 사용하는 대신, 리스펙스는 깨끗하고 함수적인 방식으로 리스트를 처리하기 위한 강력한 고차 함수를 제공합니다. 이 가이드에서는 가장 필수적인 두 함수인 map과 filter를 소개합니다.

map으로 모든 항목 변환하기

숫자 리스트가 있고, 모든 숫자를 두 배로 만든 새 리스트를 만들고 싶다면 어떨까요? 이는 map에 완벽한 작업입니다.

map 함수는 함수와 리스트를 받아, 원본 리스트의 모든 단일 항목에 함수를 적용하고, 그 결과를 담은 새 리스트를 반환합니다. 새 리스트는 항상 원본과 동일한 수의 항목을 가집니다.

구문: (map FUNCTION LIST)

예제: 숫자 두 배로 만들기

LISPEX
(define numbers (list 10 20 30 40))

(define doubled-numbers
  (map (lambda (x) (* x 2)) numbers))

;; doubled-numbers의 값은 이제 (list 20 40 60 80) 입니다
;; 원본 `numbers` 리스트는 변경되지 않습니다.

이 예제에서 (lambda (x) (* x 2)) 함수가 각 원소에 적용되어 새 리스트가 만들어집니다.

filter로 항목 선택하기

이제, 숫자 리스트가 있고 짝수인 것들만 남기고 싶다면 어떨까요? 이는 filter의 역할입니다.

filter 함수는 "조건자(predicate)" 함수(#t 또는 #f를 반환)와 리스트를 받습니다. 모든 항목에 조건자를 적용하고, 결과가 #t인 항목만 담은 새 리스트를 반환합니다.

구문: (filter PREDICATE_FUNCTION LIST)

예제: 짝수 찾기

LISPEX
(define numbers (list 1 2 3 4 5 6 7 8))

(define even-numbers
  (filter (lambda (n) (= (modulo n 2) 0)) numbers))

;; even-numbers의 값은 이제 (list 2 4 6 8) 입니다

함께 사용하기: 데이터 파이프라인

진정한 힘은 이 함수들을 함께 연결하여 데이터 처리 파이프라인을 만들 때 나옵니다.

실용적인 문제를 하나 풀어 봅시다. 숫자 리스트에서 5보다 큰 숫자를 모두 찾고, 각각을 설명하는 문자열로 이루어진 새 리스트를 만듭니다.

LISPEX
(define all-scores (list 2 8 5 10 3 7))

;; 1단계: 5보다 큰 점수만 남도록 필터링합니다.
(define high-scores (filter (lambda (score) (> score 5)) all-scores))
;; high-scores ⇒ (list 8 10 7)

;; 2단계: 높은 점수들을 포맷된 문자열로 매핑합니다 (string-append 사용).
(define report
  (map (lambda (score)
         (string-append "High score: " (number->string score)))
       high-scores))
;; report의 값은 이제 (list "High score: 8" "High score: 10" "High score: 7") 입니다

더 간결하게 쓰려면 이 호출들을 중첩할 수도 있습니다.

LISPEX
(map (lambda (score) (string-append "High score: " (number->string score)))
     (filter (lambda (score) (> score 5))
             (list 2 8 5 10 3 7)))

결론

map과 filter를 사용하면 전통적인 루프 없이도 데이터를 다루는 코드를 읽기 쉽게 작성할 수 있습니다. 이런 함수형 접근은 리스펙스에서 자주 쓰는 방식입니다.