简化函数输出不完全符合预期



我正在尝试编写一个函数来简化任意布尔表达式列表,但我的函数在某些测试中失败了。

(defn sim
[expression]
(if (some true? expression)
true
(if (= (count expression) 2)
(if (some false? expression)
false
(if (map simple-symbol? expression)
(if (= (count expression) 2)
(drop 1 expression)
expression)))
(if (some simple-symbol? (drop 1 expression))
(filter simple-symbol? expression)))))

当我使用(sim '(or x false))调用时,我希望输出是(x)的,但它返回(or x)。相反,当我使用(sim '(or x))调用时,我的输出会按预期(x)

类似的东西怎么样?这仅适用于or,但我相信我们可以对and和其他布尔运算符做同样的事情。

(defn simplify-or [exp]
(let [op (first exp)
args (rest exp)]
(when (= op 'or)
(let [nf-args (filter #(symbol? %) args)]
(if (some true? args)
true
(case (count nf-args)
0 false
1 (first nf-args)
(concat (list op) nf-args)))))))

结果:

(simplify-or '(or false))       
=> false
(simplify-or '(or true))       
=> true
(simplify-or '(or x true y false))       
=> true
(simplify-or '(or x y false))       
=> (or x y)
(defn simplify-or
[[op & args]]
(let [args-without-false (remove false? args)]
(cond
(some true? args-without-false) true
(= 1 (count args-without-false)) args-without-false
(empty? args-without-false) false
:otherwise (conj args-without-false op))))
(simplify-or '(or x false y))
#=> (or x y)
(simplify-or '(or x))
#=> (x)
(simplify-or '(or x true y false))
#=> true
(simplify-or '(or false false)
#=> false

我担心的是这里的一些不一致,(x)是什么? 为什么不直接x?就像我们返回的方式一样truefalse.

(require '[clojure.walk :as w])
(defmulti dispatch first)
(defmethod dispatch 'or
[[op & args]]
(if (contains? (into #{} args) true)
true
(case (count (remove false? args))
0 false
1 (first (remove false? args))
(cons op (remove false? args)))))
(defmethod dispatch 'and
[[op & args]]
(if (contains? (into #{} args) false)
false
(case (count (remove true? args))
0 false
1 (first (remove true? args))
(cons op (remove true? args)))))
(defmethod dispatch :default [x] x)
(defn simplify [x]
(prn (w/postwalk (fn [x]
(if (and (list? x) (seq x))
(dispatch x)
x))
x)))
(simplify '(or x false))
(simplify '(or x (or y false) z false))
(simplify '(or x (or y false) (and z false)))
(simplify '(or x false y))
(simplify '(or x))
(simplify '(or x (or x true y false)))
(simplify '(or false false (and true true)))

最新更新