clojure core.logic 计算集合中的元素

标签 clojure clojure-core.logic

我尝试在 core.logic 中做这样的事情

(defn count-different-elements-in-list [coll]
  (count (set coll)))

这适用于整数

(should= 1 (count-different-elements-in-list '(1 1 1)))
(should= 2 (count-different-elements-in-list '(1 1 2)))
(should= 3 (count-different-elements-in-list '(1 3 2)))

但现在我正在尝试使用 core.logic 来解决一些问题,结果变得很乱

(run* [a b c]
  ;;the variables get values between 1 and 3
  (fd/in a b c (fd/interval 1 3))
  ;; in the list there should only be 2 different values
  (== 2 (count-different-elements-in-list '(a b c))))

但问题来了,a b c 没有作为值传递给函数。它们作为变量传递。使用三个变量 count-different-elements-in-list 总是返回 3 并且 core.logic 找不到解决方案(空列表)。

但我正在寻找这个结果。

([1 1 2] [1 2 1] [2 1 1] 
 [1 1 3] [1 3 1] [3 1 1]
 [2 2 1] [2 1 2] [1 2 2]
 [2 2 3] [2 3 2] [3 2 2]
 [3 3 1] [3 1 3] [1 3 3]
 [3 3 2] [3 2 3] [2 3 3])

最佳答案

您需要将core.logic/project 逻辑变量转换为非关系目标,例如普通函数count-different-elements-in-list。不幸的是,您不能投影有限域逻辑变量,例如abc,它们不受约束到一个单一的值(value)。 (参见:this question)

在您的示例中,您可以将 fd/infd/interval 换成生成的范围和 membero。这将删除不受约束的有限域变量,保留整数的范围约束,并允许进行投影。

(def interval (vec (range 1 4)))
(run* [a b c]
  (membero a interval)
  (membero b interval)
  (membero c interval)
  (project [a b c]
    (== 2 (count-different-elements-in-list (list a b c)))))

关于clojure core.logic 计算集合中的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19018637/

相关文章:

clojure - Clojure 宏生成的代码中的反射警告

clojure - 如何在 Clojure 中忘记延迟序列的 head(GC'd)?

clojure - 在 webnoir 中以编程方式获取主机地址

clojure - 使用 clojure 的 core.logic/core.match 解决 Dinesman 的多户住宅示例

oop - "Many functions operating upon few abstractions"原理 vs 面向对象

clojure - 为什么 run* 不适用于 core.logic 中的自然数?

clojure - 如何简单地编写一个拦截器,使用 Pedestal 从 get/post 请求中提取 json

clojure - 关系数据库语言和逻辑编程有何相似之处?

clojure - 使用集合时的 ​​core.logic stackoverflow

Clojure 相当于 Erlang 的 DETS/Persistent-Maps