Сварганил оператор CASE, на сей раз попытался добавить "синтаксический сахар" (пока не очень удачно вышло, но уже кое-что):
CASE-TEST: ( CASE "Apple" ( ( ( < 5 )
( FORMAT "Less than 5~%" )
)
( ( = 5 )
( FORMAT "Equals 5~%" )
)
( ( > 5 )
( FORMAT "Greater than 5~%" )
)
( ( = "Apple" )
( FORMAT "It's an apple!~%" )
)
)
( FORMAT "I dont know what is it~%" )
)
Вычисление этого кода печатает "It's an apple!".
В общем виде структура такая:
( CASE (expr)
(
( ( cond-p-1 ) ( instr-1 ) )
( ( cond-p-2 ) ( instr-2 ) )
..
( ( cond-p-n ) ( instr-n ) )
)
( when-not-of-it-all-instr )
)
Что неудобно: если вместо правильных одноместных предикатов (функций одного параметра, возвращающих булеву истину, если выполнено некое условие, запрограммированное в этой самой функции) указан вызов какой-нибудь обычной функции, например ( > 5 ), то к списку её кода пристыковывается результат вычисления expr и получается так:
( > 5 expr )
Что даёт результат, совершенно противоположный очевидно-ожидаемому: например, если expr было равно 2, то записав условие в виде ( > 5 ) мы будем ожидать, что этот предикат НЕ сработает, в то время как в реальности ( > 5 2 ) возвращает, очевидно, T и далее вызывается связанный с этим условием код.
Очевиден так же и метод обхода, хоть он и немного громоздкий - в качестве предикатов для неких "временных", нужных только в этом месте, условий, надо использовать лямбды! Т.е. на месте ( > 5 ) надо записать как-то так:
(apply ( lambda (x) ( > x 5 ) ) )
Этот код должен работать правильно. И сейчас я это проверю...
...
????
!!!!
...
( CASE "Apple" ( ( ( = 5 )
( FORMAT "Equals 5~%" )
)
( ( APPLY ( LAMBDA ( X )
( > X 5 )
)
)
( FORMAT "Less than 5~%" )
)
( ( APPLY ( LAMBDA ( X )
( < X 5 )
)
)
( FORMAT "Greater than 5~%" )
)
( ( APPLE-P )
( FORMAT "It's an apple!~%" )
)
)
( FORMAT "I dont know what to do with ~a~%" $ )
)
It's an apple!
Сами логичские функции ещё оооочень далеки от совершенства в части касающейся сравнения данных разных типов (сейчас всё просто - если тип не совпадает, возвращается NIL, даже если мы сравниваем целочисленный 0 и, например, null-строку (не пустую, которая "", а вообще null)).
APPLE-P это как раз предикат, который проверяет равенство своего аргумента строке "Apple".
$ - это локальный символ, которому присваивается вычисленное значение expr. Вот что будет, если тот же CASE запустить с чем-то, чего он не знает:
( CASE "Pineapple" ( ( ( = 5 )
( FORMAT "Equals 5~%" )
)
( ( APPLY ( LAMBDA ( X )
( > X 5 )
)
)
( FORMAT "Less than 5~%" )
)
( ( APPLY ( LAMBDA ( X )
( < X 5 )
)
)
( FORMAT "Greater than 5~%" )
)
( ( APPLE-P )
( FORMAT "It's an apple!~%" )
)
)
( FORMAT "I dont know what to do with ~a~%" $ )
)
I dont know what to do with "Pineapple"
РАБОТАЕТ!
Правда, это совсем не то же самое, что CASE в Common Lisp. И не совсем COND. Переименовал в "SELECTOR", пусть будет.. и тут же, пока горячо, накропал более привычный и почти стандартный CASE. Отличие только одно - не используется слово "otherwise", вместо этого код для "никакого" условия вынесен как бы в отдельную ветку. Вот:
( CASE "Beta" ( ( "Kenobi" "Jedi" )
( ( 5 99 1024 )
"Kinda integer" )
( ( "Alpha" 1 "Beta" )
( FORMAT "UncommonLisp is awesome!~%" )
)
)
( FORMAT "I dont know what to do with ~a~%" $ )
)
UncommonLisp is awesome!