我正在尝试编写一个函数,该函数将简化布尔表达式的任意列表,但是我的函数无法通过某些测试。
(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)
。
答案 0 :(得分:1)
这些方面的情况如何?这仅适用于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)
答案 1 :(得分:0)
(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
?与我们只返回true
或false
的方式相同。
答案 2 :(得分:0)
(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)))