Я написал функцию в Clojure, которая должна взять логическое выражение и вернуть эквивалентное выражение, где все операторы not
действуют непосредственно на переменные, например:Вложенные операторы карты в Clojure не оцениваются должным образом, похоже на LazySeq
(not (and p q r))
становится
(or (not p) (not q) (not r))
Он использует законы де Моргана подталкивать not
S внутрь, а если 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
работает сама по себе. Позвольте мне показать вам:
Если я пишу следующее в РЕПЛ:
(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
. Я попробовал запустить (into (list))
на test1
, чтобы преобразовать его в PersistentList
, а также doRun
и doAll
, без каких-либо результатов. Могу ли я как-то остановить мой оператор map not-ify
от возвращения LazySeq
?
'map' всегда будет возвращать lazyseq. – jmargolisvt
Есть ли у вас какие-либо предположения о том, как я могу решить проблему? Невозможно ли иметь вложенные выражения 'map'? – Henrik
Это как «уведомление» определено ?: '(defn not-ify [expr] (list 'not expr))' – Thumbnail