【发布时间】:2016-05-21 14:41:52
【问题描述】:
我在 Clojure 中编写了一个函数,它应该采用逻辑表达式并返回一个等效表达式,其中所有 not 语句都直接作用于变量,如下所示:
(not (and p q r))
变成
(or (not p) (not q) (not r))
它使用德摩根定律将nots 向内推,如果not 直接作用于另一个not 语句,它们就会取消。代码如下所示:
(defn transform [expr]
(if
(list? expr)
(if
(=
'not
(first expr)
)
(if
(list? (nth expr 1))
(if
(=
'not
(first (nth expr 1))
)
(transform (first (rest (first (rest expr)))))
(if
(=
'and
(first (nth expr 1))
)
(cons
'or
(map
transform
(map
not-ify
(rest (first (rest expr)))
)
)
)
(if
(=
'or
(first (nth expr 1))
)
(cons
'and
(map
transform
(map
not-ify
(rest (first (rest expr)))
)
)
)
expr
)
)
)
expr
)
expr
)
expr
)
)
问题出在这部分:
(map
transform
(map
not-ify
(rest (first (rest expr)))
)
)
第一个map 语句使用函数not-ify(请原谅双关语)基本上在每个语句之前放置一个not。那部分有效。但是,输出不适用于map transform,尽管map transform 部分本身可以工作。让我告诉你:
如果我在 REPL 中写下以下内容:
(def expr '(not (and q (not (or p (and q (not r)))))))
(map
not-ify
(rest (first (rest expr)))
)
我得到了输出((not q) (not (not (or p (and q (not r))))))
如果我随后获取该输出并运行(map transform '((not q) (not (not (or p (and q (not r))))))),我将得到输出((not q) (or p (and q (not r))))。到目前为止一切顺利。
但是,如果我一次运行它,像这样:
(map
transform
(map
not-ify
(rest (first (rest expr)))
)
)
我得到的是这个输出:((not q) (not (not (or p (and q (not r))))))。
如果运行
(def test1
(map
not-ify
(rest (first (rest expr)))
)
)
(map transform test1)
我也收到了((not q) (not (not (or p (and q (not r))))))。
但是如果我跑了
(def test2 '((not q) (not (not (or p (and q (not r)))))))
(map transform test2)
我再次得到正确的结果:((not q) (or p (and q (not r))))。
我的猜测是,这在某种程度上与 map not-ify 输出 (test1) 的类型为 LazySeq 有关,而如果我手动输入输入 (test2),它会变成 PersistentList。我尝试在test1 上运行(into (list)) 将其转换为PersistentList,以及doRun 和doAll,但没有结果。我能否以某种方式阻止我的 map not-ify 语句返回 LazySeq?
【问题讨论】:
-
map将始终返回一个lazyseq。 -
你对我如何解决这个问题有什么建议吗?不能嵌套
map语句吗? -
notify是这样定义的吗?:(defn not-ify [expr] (list 'not expr))
标签: clojure nested boolean-logic lazy-sequences map-function