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

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 相同的方式只是 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)))