리스펙스는 명령형 구문보다는 값을 평가하는 표현식을 통해 주로 실행 흐름을 관리합니다. 이러한 함수형 접근 방식은 더 예측 가능하고 조합 가능한 코드를 만듭니다. 이 섹션에서는 프로그램 흐름을 제어하기 위한 주요 메커니즘을 다룹니다.
if를 사용한 조건부 평가
조건부 분기를 위한 주요 도구는 if 표현식입니다. 조건을 평가하고, 그 결과에 따라 두 가지 가능한 표현식 중 하나를 평가합니다.
구문: (if CONDITION_EXPR TRUE_EXPR FALSE_EXPR)
- 먼저
CONDITION_EXPR를 평가합니다. - 결과가 참 같은 값(즉
#f가 아닌 값)이면TRUE_EXPR의 결과를 반환합니다. - 결과가
#f이면FALSE_EXPR의 결과를 반환합니다.
(define temperature 25)
(define clothing-advice
(if (> temperature 20)
"It's warm, wear a t-shirt!" ; 덥네요, 티셔츠!
"It's cool, consider a jacket.")) ; 서늘하네요, 재킷 고려
;; clothing-advice ⇒ "It's warm, wear a t-shirt!"
;; 중첩 if
(define grade 85)
(define letter-grade
(if (>= grade 90)
"A"
(if (>= grade 80)
"B"
(if (>= grade 70)
"C"
"F"))))
;; letter-grade ⇒ "B"
논리 연산자: and 및 or
리스펙스는 논리 조합을 위해 and 및 or 연산자를 제공합니다. 이들은 단축 평가를 사용합니다.
(and ...): 왼쪽에서 오른쪽으로 평가합니다.#f를 만나면 즉시#f를 반환합니다. 모두 참 같은 값이면 마지막 값이 결과입니다.(or ...): 왼쪽에서 오른쪽으로 평가합니다. 첫 번째 참 같은 값을 반환합니다. 없으면#f입니다.
(define user-is-admin #t)
(define has-permission #t)
;; 둘 다 참: 마지막 값 반환
(and user-is-admin has-permission "Access Granted") ; ⇒ "Access Granted"
;; #f에서 단축 평가: 두 번째 식은 평가되지 않음
(and #f (some-expensive-call)) ; ⇒ #f
반복
함수형 뿌리에 충실하게, 리스펙스는 for나 while과 같은 전통적인 루프보다는 반복에 대해 선언적 접근 방식을 선호합니다. 이는 재귀(recursion)와 고차 함수(higher-order functions)를 통해 이루어집니다.
재귀를 사용한 반복
재귀는 특히 리스트에 대해 반복을 수행하는 자연스러운 방법입니다. 패턴은 리스트의 첫 번째 요소를 처리한 다음 나머지 리스트에 대해 함수를 재귀적으로 호출하는 것을 포함합니다.
예시: 리스트의 숫자 합계 구하기
(define (sum-list xs)
(if (null? xs)
0 ; 기저 사례
(+ (car xs) (sum-list (cdr xs))))) ; 재귀 단계
(sum-list (list 10 20 30 40)) ; ⇒ 100
고차 함수를 사용한 반복
컬렉션을 처리하는 더 선언적이고 종종 선호되는 방법은 map, filter, reduce와 같은 고차 함수를 사용하는 것입니다.
(define numbers (list 1 2 3 4 5))
;; map: 모든 요소에 함수를 적용
(define squared (map (lambda (n) (* n n)) numbers))
;; squared ⇒ (list 1 4 9 16 25)
;; filter: 조건을 만족하는 요소만 유지
(define evens (filter (lambda (n) (= (modulo n 2) 0)) numbers))
;; evens ⇒ (list 2 4)
;; reduce: 모든 요소를 하나의 값으로 결합
(define sum (reduce (lambda (acc elem) (+ acc elem)) 0 numbers))
;; sum ⇒ 15