clojure logic clojure-core.logic minikanren

clojure - ¿Cómo simular una ''unión externa'' en core.logic?



clojure-core.logic minikanren (2)

Conda puede complejizar el código, usando nafc, puede reordenar los objetivos más fácilmente si lo desea. ¡Esto todavía no es relacional! :)

(ns somenamespace (:refer-clojure :exclude [==]) (:use [clojure.core.logic][clojure.core.logic.pldb])) (db-rel items Name Color) (db-rel restricted-to Country Name) (db-rel not-allowed-in Country Name) (def stackoverflow-db (db [items ''Purse ''Blue] [items ''Car ''Red] [items ''Banana ''Yellow] [restricted-to ''US ''Car] [not-allowed-in ''UK ''Banana] [not-allowed-in ''France ''Purse])) (defn get-items-colors-for-country [country] (with-db stackoverflow-db (run* [it co] (items it co) (nafc not-allowed-in country it) (conde [(restricted-to country it)] [(nafc #(fresh [not-c] (restricted-to not-c %)) it)])))) (get-items-colors-for-country ''US) ;=> ([Purse Blue] [Banana Yellow] [Car Red]) (get-items-colors-for-country ''UK) ;=> ([Purse Blue]) (get-items-colors-for-country ''France) ;=> ([Banana Yellow]) (get-items-colors-for-country ''Australia) ;=> ([Purse Blue] [Banana Yellow])

Para más ejemplos: https://gist.github.com/ahoy-jon/cd0f025276234de464d5

Acabo de empezar a jugar con core.logic, y para trabajar en ello estoy intentando implementar algo simple que es similar a un problema en el que estoy trabajando actualmente de manera profesional. Sin embargo, una parte del problema me ha dejado perplejo ...

Como simplificación de mi ejemplo, si tengo un catálogo de artículos, y algunos de ellos solo están disponibles en ciertos países, y algunos no están disponibles en países específicos. Me gustaría poder especificar la lista de elementos y las excepciones, algo así como:

(defrel items Name Color) (defrel restricted-to Country Name) (defrel not-allowed-in Country Name) (facts items [[''Purse ''Blue] [''Car ''Red] [''Banana ''Yellow]]) (facts restricted-to [[''US ''Car]]) (facts not-allowed-in [[''UK ''Banana] [''France ''Purse]])

Si es posible, prefiero no especificar la entrada permitida para todos los países, ya que el conjunto de elementos con restricciones es relativamente pequeño, y me gustaría poder realizar un solo cambio para permitir / excluir un elemento para un determinado artículo. país.

¿Cómo puedo escribir una regla que ofrezca la lista de elementos / colores para un país, con las siguientes restricciones:

  • El artículo debe estar en la lista de artículos.
  • El país / elemento no debe estar en la lista de "no permitido"
  • Ya sea:
    • No hay ningún país en la lista restringida para ese artículo
    • El par de país / elemento está en la lista de restringidos a

Hay alguna manera de hacer esto? ¿Estoy pensando en las cosas totalmente de la manera incorrecta?


Por lo general, cuando comienza a negar los objetivos en la programación lógica, necesita alcanzar operaciones no relacionales (corte en Prolog, conda en core.logic).

Esta solución solo debe llamarse con argumentos básicos.

(defn get-items-colors-for-country [country] (run* [q] (fresh [item-name item-color not-country] (== q [item-name item-color]) (items item-name item-color) (!= country not-country) (conda [(restricted-to country item-name) (conda [(not-allowed-in country item-name) fail] [succeed])] [(restricted-to not-country item-name) fail] ;; No entry in restricted-to for item-name [(not-allowed-in country item-name) fail] [succeed])))) (get-items-colors-for-country ''US) ;=> ([Purse Blue] [Banana Yellow] [Car Red]) (get-items-colors-for-country ''UK) ;=> ([Purse Blue]) (get-items-colors-for-country ''France) ;=> ([Banana Yellow]) (get-items-colors-for-country ''Australia) ;=> ([Purse Blue] [Banana Yellow])

Solución completa