1

我正在查看一个使用parsley解析其语法的 clojure 重构库。我将欧芹升级到 0.9.1,然后一个功能失败了。

下面是该函数的作用:假设我们有"(defn a [b] (:foo b))",重构工具将解析参数和映射查找:[b](:foo b). 然后转换(:foo b)为地图:并用地图的值{b (foo :foo)}替换符号。我终于应该得到了。b[b](foo :foo){(foo :foo)}

以下代码用于最后一步:

clojure.walk/postwalk-replace {#net.cgrand.parsley.Node{:tag :atom, :content ["b"]} #net.cgrand.parsley.Node{:tag :map, :content ["{" #net.cgrand.parsley.Node{:tag :atom, :content ["foo"]} #net.cgrand.parsley.Node{:tag :whitespace, :content [" "]} #net.cgrand.parsley.Node{:tag :atom, :content [":foo"]} #net.cgrand.parsley.Node{:tag :whitespace, :content [" "]} "}"]}}
                           #net.cgrand.parsley.Node{:tag :vector, :content ["[" #net.cgrand.parsley.Node{:tag :atom, :content ["b"]} "]"]}

它报告:`UnsupportedOperationException 无法创建空:net.cgrand.parsley.Node net.cgrand.parsley.Node (parsley.clj:19)

但是,当我 pprint{#net.cgrand.parsley.Node{:tag :atom, :content ["b"]} #net.cgrand.parsley.Node{:tag :map, :content ["{" #net.cgrand.parsley.Node{:tag :atom, :content ["foo"]} #net.cgrand.parsley.Node{:tag :whitespace, :content [" "]} #net.cgrand.parsley.Node{:tag :atom, :content [":foo"]} #net.cgrand.parsley.Node{:tag :whitespace, :content [" "]} "}"]}}

#net.cgrand.parsley.Node{:tag :vector, :content ["[" #net.cgrand.parsley.Node{:tag :atom, :content ["b"]} "]"]}

然后将它们传递给 postwalk:

(clojure.walk/postwalk-replace {{:tag :atom, :content ["b"]}
                            {:tag :map,
                             :content
                             ["{"
                              {:tag :atom, :content ["foo"]}
                              {:tag :whitespace, :content [" "]}
                              {:tag :atom, :content [":foo"]}
                              {:tag :whitespace, :content [" "]}
                              "}"]}}
                           {:tag :vector, :content ["[" {:tag :atom, :content ["b"]} "]"]})

一切都很好,我得到了我想要的{:content ["[" {:content ["{" {:content ["foo"], :tag :atom} {:content [" "], :tag :whitespace} {:content [":foo"], :tag :atom} {:content [" "], :tag :whitespace} "}"], :tag :map} "]"], :tag :vector}

我的问题是:#net.cgrand.parsley.Node欧芹中的含义是什么?为什么在我删除这些符号(使用 pprint)之后问题就消失了。

4

1 回答 1

2

问题是 Parsley 的节点是记录,而不是常规映射。#net.cgrand.parsley.Node{...}是此记录类型的文字表示法。记录不能被清空(与 一样clojure.core/empty),clojure.walk函数依赖于清空集合empty,因此clojure.walk函数不能对记录进行操作。

碰巧pprint在打印记录时省略了标签——它只是将它们打印为常规地图——所以如果你读回pprinted 表示,你会得到一个地图,然后可以清空它,这样你就可以将它传递给postwalk.

正确的行动方案取决于您希望完成的具体目标。如果你想要实际Node的实例,你需要编写自己的 tree walker(也许正在适应clojure.walk/walk);如果您对常规地图没问题,您可以编写一个非常简单的 tree walker 来将Nodes 替换为 Parsley 输出中的地图,然后clojure.walk在转换后的树上使用。

于 2013-06-02T03:19:13.643 回答