cond - многовариантное условие

Sergey ShishkinSergey Shishkin
2 min read

(cond ('any1 . prg1) ('any2 . prg2) ..) -> any

Если любое из условий anyN не равно NIL, выполняется prgN и возвращается результат. В противном случае (все условия равны NIL) возвращается NIL.

См. также nond when and if if2

Пример

: (cond
   ((= 3 4) (println 1)) 
   ((= 3 3) (println 2))
   (T (println 3)) )
2
-> 2

https://software-lab.de/doc/refC.html#cond

Третье условие T (аналог else) не проверяется, так как уже найдено истинное.

Аналог в JS

if (condition1) { action1(); }
else if (condition2) { action2(); }
else { actionN(); }

Код определения

   (NIL "cond" _Cond)

glob.l

# (cond ('any1 . prg1) ('any2 . prg2) ..) -> any
(de _Cond (Exe) */ Принимает один аргумент Exe — список условий и действий в формате cond
   (let X Exe */ Создаёт локальную копию списка условий Exe в переменной X 
      (loop */ Запускает бесконечный цикл (прерывается только при выполнении условия или конце списка)
         (? (atom (shift X)) $Nil) */ Проверяет, является ли элемент атомом (признак конца списка), (shift X) извлекает и удаляет первый элемент из X. Если X пуст (достигнут атом), возвращает $Nil (ложь).
         (let Y (car X) */ Берёт первый оставшийся элемент X (это пара (условие . действие)).
           (? (not (nil? (eval (car Y)))) */ проверяет, что условие не NIL (т.е. истинно). (car Y) — извлекает условие из пары и (eval ...) — вычисляет условие.
               (set $At @) */ Сохраняет результат вычисления условия в глобальную переменную $At (можно использовать позже).
               (run (cdr Y)) */ Если условие истинно, выполняет действие (все выражения после условия).
 ) ) ) ) )
  • llvm~_Cond (634 "src/flow.l" llvm pico)

  • llvm~cond (1314 "src/lib/llvm.l" llvm pico)

  • pico~cond (634 "src/flow.l" llvm pico)

Особенности реализации

  1. Рекурсия через цикл
    Вместо рекурсии используется loop + shift, что эффективнее по памяти.

  2. Сохранение результата
    Переменная $At хранит последнее вычисленное условие (может быть полезно для отладки).

  3. Гибкость
    Поддерживает любое количество условий и действий, включая T (всегда истинно). Использует eval и динамические переменные ($At).

Как видим, небольшой (!?) список зависимостей - not nil? loop let run cdr car shift set atom eval

P.S. Определение небольшое и я решил посмотреть как может выглядеть “полное описание“ функции. Кажется “погорячился” с комментариями в коде определения. Надо как-то по-другому сделать в следующий раз на примере другой “небольшой“ функции.

0
Subscribe to my newsletter

Read articles from Sergey Shishkin directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sergey Shishkin
Sergey Shishkin

Всегда чему-то учусь!