Clojure:使用多个参数简化逻辑表达式

Clojure:使用多个参数简化逻辑表达式,clojure,functional-programming,logic,Clojure,Functional Programming,Logic,我是Clojure的新手,试图编写一个简化逻辑表达式的程序。例如: (or x false) => x (or true x) => true (or x y z) => (or x(or y z)) 我相信,我已经找到了将表达式简化为两个参数的方法。但是,我不知道如何简化包含两个以上参数的表达式。我试图使用第n个函数尝试对表达式进行分区,但这似乎使事情更加复杂: (defn pre-simplify [expression n] (cond (= n 0) (n

我是Clojure的新手,试图编写一个简化逻辑表达式的程序。例如:

(or x false) => x
(or true x) => true
(or x y z) => (or x(or y z))
我相信,我已经找到了将表达式简化为两个参数的方法。但是,我不知道如何简化包含两个以上参数的表达式。我试图使用第n个函数尝试对表达式进行分区,但这似乎使事情更加复杂:

(defn pre-simplify [expression n]
  (cond
    (= n 0) (nth expression 0)
    (= n 1) (nth expression 1)
    (= n 2) (nth expression 2)
    (= n 3) (nth expression 3)
   )
)
这是Simplify函数的代码:

(defn simplify
  ([op arg1]                                                
    (cond
      (and (= arg1 'true) (= op 'not)) false
      (and (= arg1 'false) (= op 'not)) true
      (= arg1 'true) true
      (= arg1 'false) false)
      ;not not x -> x
    )
  ([op arg1 arg2]                                         
    (cond
      (seq? arg1) (let [arg1 (simplify op arg1)]))
    (cond
      (seq? arg2) (let [arg2 (simplify op arg2)]))
    (cond
      (= op 'or) (
                 (cond
                    (and (= arg1 'false) (= arg2 'false)) false
                    (or (= arg1 'true) (= arg2 'true)) true
                    (and (= arg1 'false) (and (not= arg2 'false) (not= arg2 'true))) arg2
                    (and ((not= arg1 'false) (not= arg1 'true)) (= arg2 'false)) arg1
                )
              )
      (= op 'and') (
                   (cond
                     (and (= arg1 'true) (= arg2 'true)) true
                     (or (= arg1 'false) (= arg2 'false)) false
                     (and (= arg1 'false) (and (not= arg2 'false) (not= arg2 'true))) arg2
                     (and ((not= arg1 'false) (not= arg1 'true)) (= arg2 'false)) arg1
                   )
             )
       )
 )
另外,我正在考虑在前两个参数之后对列表的其余部分使用递归。例如,我尝试在两个以上的参数上执行此操作:

    ([op arg1 arg2 & rest]                                    
      (simplify op (list (op arg1 (op arg2 rest))))))  

这看起来像是家庭作业,所以让我请你从另一个角度考虑这个问题。 在Clojure

  • 表达式是以符号
    开头的表达式列表(或其他序列)
  • 表达式是以开头的表达式列表 符号
    
    
表达式也可以是

  • 参数或其他本地名称的符号,或
  • 文本
    true
    false
要简化表达式,请执行以下操作:

  • 如果它是一个序列(使用
    seq?
    来测试它),
    简化它的
    参数(列表中除
    第一个
    -
    其余
    之外的所有元素都将提供这些参数)。您可以使用
    map
    进行递归调用
  • 然后,例如,如果操作符(第一个
    元素)是
    符号,
    
    • 如果操作数中存在任何
      false
      文字(您可以使用
      some
      要测试这一点,请将整个表达式替换为
      false
    • 如果不是,则删除
      任何
      true
      文字
这些简化可能会为其他人打开道路。比如说,

  • (and)
    只是
    正确
  • (和x)
    只是
    x
无论你做什么,在开发的过程中测试你的函数,确保它做你认为它做的事情。有一次我漏掉了接线员。我摔倒在
(和x)
箱子上

还有一个需要考虑的问题是,您需要验证表达式是否有效以及验证的程度

  • 未知操作符呢
  • 您是否需要验证符号是否引用了某些内容。如果是,, 怎么做
注释

  • 我假设我们可以忽略副作用:表达式所做的只是 返回一个值
  • 我不会用
    (或x(或y z))
    替换
    (或x(或y z)
    。这实现了 什么都不做,使用一个额外的标记:与简化相反
  • 任何Clojure值——一个数字,甚至是一个函数——都在逻辑上起作用 true,除了逻辑上为false的
    false
    nil
    。是否 这和你的问题有关,我不知道
  • 如果您觉得自己很聪明,您可能能够参数化
    根据您忽略的文字(
    true
    分别为false
    ),您结束时使用的和返回的 当没有争论的时候

整个问题被认为是难以解决的。如果你能找到一个有效的解决方案,你将举世闻名

一行中的3个
cond
s应该做什么?我可能很累,但前两个应该对任何事情都没有影响。您正在创建一个
arg1
arg2
的局部阴影,然后将其丢弃。您是偶然从命令式编程中获得的吗?