Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 如何模拟';外部连接';核心逻辑?_Clojure_Logic_Clojure Core.logic_Minikanren - Fatal编程技术网

Clojure 如何模拟';外部连接';核心逻辑?

Clojure 如何模拟';外部连接';核心逻辑?,clojure,logic,clojure-core.logic,minikanren,Clojure,Logic,Clojure Core.logic,Minikanren,我刚刚开始使用core.logic,为了解决这个问题,我正在尝试实现一些简单的东西,类似于我目前正在处理的一个问题。然而,问题的一部分让我感到困惑 作为我的示例的简化,如果我有一个项目目录,其中一些仅在某些国家可用,而一些在特定国家不可用。我希望能够指定项目列表和例外情况,例如: (defrel items Name Color) (defrel restricted-to Country Name) (defrel not-allowed-in Country Name) (facts it

我刚刚开始使用core.logic,为了解决这个问题,我正在尝试实现一些简单的东西,类似于我目前正在处理的一个问题。然而,问题的一部分让我感到困惑

作为我的示例的简化,如果我有一个项目目录,其中一些仅在某些国家可用,而一些在特定国家不可用。我希望能够指定项目列表和例外情况,例如:

(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]])
如果可能,我不希望为所有国家/地区指定allowed in,因为具有限制的项目集相对较小,并且我希望能够对给定国家/地区的项目进行单个更改以允许/排除

我如何编写一个规则,给出一个国家/地区的项目/颜色列表,并有以下限制:

  • 项目必须在项目列表中
  • 国家/地区/项目不得在“不允许进入”列表中
  • 要么:
    • 该项目的限制列表中没有国家/地区
    • 国家/地区/项目对位于限制列表中

有没有办法做到这一点?我是否以完全错误的方式思考问题?

通常,当您开始否定逻辑编程中的目标时,您需要实现非关系操作(切入Prolog,进入core.logic中的conda)

此解决方案只能使用基本参数调用

(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])

康达可能会使代码复杂化,使用nafc,如果您愿意,您可以更轻松地重新排序目标。 这仍然是非关系性的!:)


更多示例:

关于“基本参数”,我假设您指的是一个值,而不是查询变量?抱歉,我最后一次学习逻辑编程是大约25年前的一门本科prolog课程……它不能是一个未绑定或未绑定的变量。如果某个值不包含未绑定的逻辑变量,则该值为接地(例如,[1 2 0.\u]不为接地)。如果函数是一个目标,并且您将查询变量作为参数传递,那么这就变得非常重要。在此要点中,
items colors for country
要求其第一个参数为ground。这个目标比我最初的答案更加灵活和可组合。例如,我们可以查询美国可用钱包的颜色@PeterHart我假设这个专业项目是基于数据库的?如果您对扩展core.logic来直接查询这个数据库感兴趣,我已经转储了一些资料,实际上所有这些都是在内存中使用集合(java代码)和/或xpath查询完成的。实际问题要复杂得多——它涉及重叠的层次结构。不幸的是,我进入环境的机会非常渺茫。不过,我会看一看你的例子,因为我试图理解这一点,这样如果我有机会提出一个案例,我就会有足够的知识来做好工作。
(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])