Ботанизм-програмизм (4).

Aug 15, 2015 00:50

Сварганил оператор 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!

uncommon lisp

Previous post Next post
Up