Как сопоставить иерархию с clojure.core.match? - PullRequest
1 голос
/ 29 марта 2012

Предположим, у меня есть специальная иерархия объектов, представленных как ключевые слова Clojure, например:

(def h 
  (-> (make-hierarchy)
      (derive :animal :feline)
      (derive :feline :cat) 
      (derive :feline :lion) 
      (derive :feline :tiger)))

Как лучше всего (желательно с использованием clojure.core.match ) написать функцию match-hierarchy, чтобы эти выдуманные примеры возвращали ожидаемые результаты:

(defn example [x y]
  (match-hierarchy h [x y]
    [:cat :cat] 0
    [:cat :feline] 1
    [:cat :animal] 2
    [:animal :animal] 3))

(example :cat :cat)
;=> 0

(example :cat :tiger)
;=> 1

(example :tiger :tiger) 
;=> 3

т.е., match-hierarchy должен возвращать значение, соответствующее первому предложению, все элементы которого либо равны соответствующему элементу сопоставляемого значения, либо его (прямым или косвенным) предкам?

Я счастлив использовать что-то нестандартное вместо make-hierarchy для создания иерархий. Я также счастлив, что не использую core.match, если доступна другая опция. Однако он мне нужен для работы с объектами уже существующих классов, такими как числа (например, я хочу сказать, что 3 это :positive-integer это :integer это :number).


Справочная информация : Я пишу сборщик игрушек x86 в Clojure, где мне нужно собрать инструкцию, основываясь на ее имени и операндах. В настоящее время мой код включает в себя что-то вроде:

(match [(-> instr name keyword) (operand-type op1) (operand-type op2)]
  ;; other options
  [:int :imm nil]  (if (= op1 3)
                     {:opcode 0xcc}
                     {:opcode 0xcd, :immediate (imm 8 op1)})

(т. Е. Инструкция INT собирается в два байта, 0xcd с последующим номером прерывания, , если - это INT 3, в этом случае это только один байт, 0xcc). Однако я нахожу это несколько уродливым и ищу более элегантный подход. Поэтому вместо этого я хотел бы сказать что-то вроде

(asm-match [(-> instr name keyword) op1 op2]
  ;; other options
  [:int 3 nil]     {:opcode 0xcc}
  [:int :imm nil]  {:opcode 0xcd, :immediate (imm 8 op1)})

1 Ответ

4 голосов
/ 30 марта 2012
(match [(-> instr name keyword) op1 (operand-type op1) (operand-type op2)]
  [:int 3 :imm nil] {:opcode 0xcc}
  [:int _ :imm nil] {:opcode 0xcd, :immediate (imm 8 op1)})

Вам это не подходит?

...