我试图让它不必完全理解代码,所以首先阅读整个问题,然后在必要时深入研究代码。
我正在尝试为模式匹配制作一个宏。 它通过获取第一个元素是要执行的匹配类型的列表来工作
示例:列表中的第一个元素是“cons”;宏会调用一个cons cons函数。
匹配函数接受一个对象和一个函数,用匹配的值调用该函数。使用cons matcher,它将使用列表的头部和尾部调用函数。
我使用“num”匹配器进行测试。它基本上是一个身份匹配器,所以它可以任意嵌套在内部,就像我在下面所做的那样。
;a macro to make debugging easier
(defmacro log [item] `(do (print ~(join [(str item) ": "])) (println ~item)))
(defn make-pattern-matcher-iter [result bindings-queue]
(println "starting next iteration")
(log bindings-queue)
(if (first bindings-queue) (println "bindings-queue does contain an element") nil)
(if (first bindings-queue)
(let [[next-symbol pattern] (first bindings-queue)
pattern-name (first pattern)
pattern-items (next pattern)
pattern-matching-function (prepend-symbol "match-" pattern-name)
gensyms-attached-to-subpatterns (map (fn [pattern]
(if (symbol? pattern)
pattern
`(~(gensym "matchbinding") ~pattern)))
pattern-items)
all-bound-symbols (map (fn [sym]
(if (symbol? sym) sym (first sym)))
gensyms-attached-to-subpatterns)
gensyms-subpattern-pairs (filter list? gensyms-attached-to-subpatterns)
rest-of-bindings-queue (next bindings-queue)
updated-bindings-queue (concat rest-of-bindings-queue
gensyms-subpattern-pairs)
subpatterns (map second gensyms-subpattern-pairs)]
(log next-symbol)
(log all-bound-symbols)
(log updated-bindings-queue)
(log gensyms-attached-to-subpatterns)
(log gensyms-subpattern-pairs)
(log subpatterns)
`(~pattern-matching-function
~next-symbol
(fn [~@all-bound-symbols] ~(make-pattern-matcher-iter result updated-bindings-queue))))
result))
(defn make-pattern-matcher [object pattern result] (make-pattern-matcher-iter result [[object pattern]]))
(defn match-num [x f]
(if (number? x) (f x) nil))
(def this-m (make-pattern-matcher-iter '(+ x y) [['object '(pair x y)]]))
(def this-n (make-pattern-matcher '15 '(num (num z)) 'z))
(= this-n this-m)
(defmacro bind-match [object pattern result] (make-pattern-matcher object pattern result))
(bind-match 15 (num (num z)) z)
问题是宏没有正确绑定“z”
日志给出了第二次迭代:
gensyms-attached-to-subpatterns: ((matchbinding8210 (num z)))
gensyms-subpattern-pairs: ()
还有其他日志消息,但这些似乎是问题所在。
了解gensyms-subpattern-pairs
的计算方法。在let块中它说:
gensyms-subpattern-pairs (filter list? gensyms-attached-to-subpatterns)
这应该取出除列表之外的所有内容,这就是所有内容,所以它不应该取出任何东西。 过滤器似乎过于激进。为什么呢?
答案 0 :(得分:1)
如您所述,gensyms-attached-to-subpatterns
的元素不是IPersistentList
s,而是Cons
es。理智检查:
(contains? (supers clojure.lang.Cons) clojure.lang.IPersistentList)
;=> false
因此,您似乎需要使用除list?
之外的其他检查。