Macros 编写宏时获取原始符号名称
我编写了以下宏,它使用自定义字符串表示形式定义记录Macros 编写宏时获取原始符号名称,macros,clojure,lisp,Macros,Clojure,Lisp,我编写了以下宏,它使用自定义字符串表示形式定义记录 (defmacro defrecord* [rname args] `(defrecord ~rname [~@args] Object (toString [_] ~(let [kvs (->> args (map (fn [arg] [(str arg ": ") arg])) (interpos
(defmacro defrecord*
[rname args]
`(defrecord ~rname [~@args]
Object
(toString [_]
~(let [kvs (->> args
(map (fn [arg] [(str arg ": ") arg]))
(interpose ", ")
(apply concat))]
`(str ~rname "(" ~@kvs ")")))))
然而,toString返回的并不完全是我所期望的
(defrecord* Foo [bar baz])
(.toString (Foo. 3 4))
> "class user.Foo(bar: 3, baz: 4)"
在这种情况下,我希望我的toString返回Foobar:3,baz:4。要获得此格式的字符串表示形式,需要做哪些更改
另外,我应该对上述代码进行哪些更改(如果有的话)以使其更地道?只需将~rname更改为~name rname:
只需将~rname更改为~name rname:
只需将~rname替换为'~rname-您需要的是实际符号Foo,而不是当前作用域中的值,即类user.Foo
您还必须以错误的顺序应用concat和interpose-您将被视为一个序列,并添加\和\空格字符,而不是单个字符串。交换后,很明显您想要的是mapcat而不是apply concat map。。。。因此,我会用以下内容替换整个let块:
`(str '~rname
"(" ~@(interpose ", "
(mapcat (fn [arg] [(str arg ": ") arg])
args))
")")
或者,如果您真的想提高性能,可以在编译时而不是运行时计算~str rname
但是请注意,从Clojure 1.3开始,记录已经以与此非常类似的方式打印,因此,如果您只是为了简化调试而这样做,请不要费心。如果您这样做是因为您稍后使用了.toString的输出…那么,无论是谁编写了该代码,都会感到羞耻,因为.toString主要用于调试内容。只需将~rname替换为'~rname-您想要的是实际的符号Foo,而不是当前作用域中的值,即类user.Foo
您还必须以错误的顺序应用concat和interpose-您将被视为一个序列,并添加\和\空格字符,而不是单个字符串。交换后,很明显您想要的是mapcat而不是apply concat map。。。。因此,我会用以下内容替换整个let块:
`(str '~rname
"(" ~@(interpose ", "
(mapcat (fn [arg] [(str arg ": ") arg])
args))
")")
或者,如果您真的想提高性能,可以在编译时而不是运行时计算~str rname
但是请注意,从Clojure 1.3开始,记录已经以与此非常类似的方式打印,因此,如果您只是为了简化调试而这样做,请不要费心。如果您这样做是因为以后使用了.toString的输出…那么,无论是谁编写了这些代码,都会感到羞耻,因为.toString主要用于调试东西。我这样做只是因为我在学习宏。:谢谢我接受这个答案。我这么做只是因为我在学习宏谢谢我接受这个答案,没问题。就惯用语而言,我认为阿马洛伊的回答没有什么可补充的。没问题。就惯用语而言,我认为阿马洛伊的回答没有什么可补充的。