2015-12-07 25 views
0

我試圖讓它不必完全理解代碼,因此先閱讀整個問題,然後根據需要深入研究代碼。過濾器過於激進

我正在嘗試爲模式匹配做一個宏。 它通過列表中的第一個元素是要執行的匹配類型來工作

例如:列表中的第一個元素是「cons」;宏會調用一個cons匹配函數。

匹配函數接受一個對象和一個函數,用匹配的值調用該函數。使用cons匹配器時,它會使用列表的頭部和尾部調用函數。

我用一個「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 [[email protected]] ~(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。在讓塊說:

gensyms-subpattern-pairs (filter list? gensyms-attached-to-subpatterns) 

這應該拿出一切,但列表,這是所有的,所以它不應該拿出任何東西。 這個過濾器看起來太過分了。爲什麼?

+0

'(map type gensyms-attached-to-subpatterns)'給了什麼? –

+0

@Elogent它給'''(clojure.lang.Cons)'''。 cons仍然是清單嗎? – phil

+0

@Elogent Aha,'''(list?(cons 4 [5]))'''返回false。如果你想給出答案,我會接受它。 – phil

回答

1

如您所述,gensyms-attached-to-subpatterns的元素不是IPersistentList s,而是Cons es。理智檢查:

(contains? (supers clojure.lang.Cons) clojure.lang.IPersistentList) 
;=> false 

所以它看起來像你需要使用其他檢查比list?

+0

具體我用'''seq?''' – phil