Fork me on GitHub
#core-logic
<
2022-04-17
>
camdez16:04:15

Hi all, I want to create a relation that models the relationship between keywords and their namespace / name components. Am I on the right track here? Is there a better way?

(defn keywordo5 [kw ns nm]
  (logic/conde
   [(logic/pred ns (some-fn string? nil?))
    (logic/pred nm string?)
    (logic/project [ns nm]
                   (logic/== kw (keyword ns nm)))]
   [(logic/pred kw keyword?)
    (logic/is ns kw namespace)
    (logic/is nm kw name)]))

;; uglier but avoids repeated calls to `logic/project`
(defn keywordo6 [kw ns nm]
  (logic/or*
   [(logic/project [ns nm]
                   (if (and (or (string? ns) (nil? ns)) (string? nm))
                     (logic/== kw (keyword ns nm))
                     logic/fail))
    (logic/project [kw]
                   (if (keyword? kw)
                     (logic/== [ns nm] [(namespace kw) (name kw)])
                     logic/fail))]))

(logic/run* [q]
  (keywordo6 q nil "bar"))
;; => (:bar)

(logic/run* [q]
  (keywordo6 q "foo" "bar"))
;; => (:foo/bar)

(logic/run* [q]
  (keywordo6 :foo/bar q "bar"))
;; => ("foo")
Is it reasonable to consider this a relation (despite dipping into the non-relational bits of core.logic), or are there ways of using this where I might run into trouble (as distinct from code which avoids all non-relational bits)?