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