map 사용하기: 하나의 생각, 여러 데이터

map 함수는 하나의 변환 규칙을 데이터 컬렉션 전체에 투영합니다. 반복의 지루함에서 벗어나, 어떻게 하나의 아이디어를 여러 데이터 조각에 일관되게 적용하여 새로운 형태의 정보를 창조하는지 배워보세요.

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

map으로 모든 항목 변환하기

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

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

구문: (map FUNCTION LIST)

예제: 숫자 두 배로 만들기

(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)

예제: 짝수 찾기

(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보다 큰 모든 숫자를 찾은 다음, 각각에 대한 설명 문자열을 포함하는 새 리스트를 만드세요.

(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") 입니다

더 간결한 코드를 위해 이 호출들을 중첩할 수도 있습니다:

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

결론

mapfilter를 사용함으로써, 전통적인 루프 없이도 데이터 조작을 위한 표현력 있고, 읽기 쉽고, 강력한 코드를 작성할 수 있습니다. 이러한 함수적 접근 방식은 Lispex 언어의 초석입니다.