리스펙스에서는 데이터 리스트를 다루는 일이 잦습니다. 전통적인 루프를 사용하는 대신, 리스펙스는 깨끗하고 함수적인 방식으로 리스트를 처리하기 위한 강력한 고차 함수를 제공합니다. 이 가이드에서는 가장 필수적인 두 함수인 map과 filter를 소개합니다.
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)))
결론
map과 filter를 사용함으로써, 전통적인 루프 없이도 데이터 조작을 위한 표현력 있고, 읽기 쉽고, 강력한 코드를 작성할 수 있습니다. 이러한 함수적 접근 방식은 Lispex 언어의 초석입니다.