简化函数输出不完全符合预期
Simplifying function output not exactly as expected
我正在尝试编写一个函数来简化任意布尔表达式列表,但我的函数未通过某些测试。
(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)
,但实际上是 returns (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
?与我们 return 相同的方式只是 true
或 false
.
(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)))
我正在尝试编写一个函数来简化任意布尔表达式列表,但我的函数未通过某些测试。
(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)
,但实际上是 returns (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
?与我们 return 相同的方式只是 true
或 false
.
(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)))