В продолжение моего предыдущего вопроса я пытаюсь реализовать простое сопоставление с образцом в Clojure.
Я бы хотел что-то вроде следующего:
(match target
[ub] expr1 ; ub should be bound to actual value in expr1
['< ub] expr2 ; match the literal less-than symbol
; and ub should be bound to actual value in expr2
[lb ub] expr3 ; lb and ub should be bound to actual values in expr3
:else expr4 ; default case if none match
)
Использование:
(match [< 5.0] ...)
должен организовать выполнение expr2
во время выполнения.
Я хотел бы написать макрос, но я не уверен в расширении.
Я рассматриваю вопрос о расширении каждого case-and-clause до let
с привязками к внутренним переменным и проверкой того, что литеральные символы ('<
) действительно соответствуют шаблону. Может быть для второго шаблона (['< ub]
):
(let [[sym1 ub] pattern]
(if (= '< sym1)
expr1)
Нужно ли использовать (gensym)
для привязок? Как?
Увеличенное изображение:
(range-case target
[0.0 < 1.0] :greatly-disagree
[< 2.0] :disagree
[< 3.0] :neutral
[< 4.0] :agree
[5.0] :strongly-agree
42 :the-answer
:else :do-not-care)
Я пытаюсь сопоставить шаблоны [...]
и преобразовать их в следующее:
[ub] (if previous-ub `(and (<= ~previous-ub ~target) (<= ~target ~ub))
`(< ~target ~ub))
['< ub] (if previous-ub `(and (<= ~previous-ub ~target) (< ~target ~ub))
`(< ~target ~ub))
[lb ub] `(and (<= ~lb ~target) (<= ~target ~ub))
['< lb ub] `(and (< ~lb ~target) (<= ~target ~ub))
[lb '< ub] `(and (<= ~lb ~target) (< ~target ~ub))
['< lb '< ub] `(and (< ~lb ~target) (< ~target ~ub))
У меня есть cond
, который проверяет, что регистр является вектором. Это сопоставление с образцом должно происходить внутри этого случая.