Управление потоком: Путь мысли

Программы не просто выполняются сверху вниз. Узнайте, как создавать ветвления в потоке мысли с помощью конструкций if, cond и case, и определять путь логики в зависимости от различных условий.

Lispex управляет потоком выполнения преимущественно через выражения, которые вычисляются в значения, а не через императивные операторы. Такой функциональный подход приводит к более предсказуемому и компонуемому коду. Этот раздел охватывает основные механизмы управления потоком программы.

Условное вычисление с помощью 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!"

;; Вложенные условные выражения
(define grade 85)

(define letter-grade
  (if (>= grade 90)
      "A"
      (if (>= grade 80)
          "B"
          (if (>= grade 70)
              "C"
              "F"))))
;; letter-grade ⇒ "B"

Логические операторы: and и or

Lispex предоставляет операторы 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. Это достигается с помощью рекурсии и функций высшего порядка.

Итерация с помощью рекурсии

Рекурсия является естественным способом выполнения итерации, особенно для списков. Шаблон включает обработку первого элемента списка и затем рекурсивный вызов функции для оставшейся части списка.

Пример: Суммирование чисел в списке

(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