제어 흐름: 생각의 경로

프로그램은 위에서 아래로만 흐르지 않습니다. if, cond, case와 같은 구문을 사용하여 생각의 흐름에 분기를 만들고, 다양한 조건에 따라 논리의 경로를 결정하는 법을 배워보세요.

리스펙스는 명령형 구문보다는 값을 평가하는 표현식을 통해 주로 실행 흐름을 관리합니다. 이러한 함수형 접근 방식은 더 예측 가능하고 조합 가능한 코드를 만듭니다. 이 섹션에서는 프로그램 흐름을 제어하기 위한 주요 메커니즘을 다룹니다.

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"

논리 연산자: andor

리스펙스는 논리 조합을 위해 andor 연산자를 제공합니다. 이들은 단축 평가를 사용합니다.

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

반복

함수형 뿌리에 충실하게, 리스펙스는 forwhile과 같은 전통적인 루프보다는 반복에 대해 선언적 접근 방식을 선호합니다. 이는 재귀(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