gpt4 book ai didi

variables - 如何在clojure 宏中绑定(bind)var 的名称和值?

转载 作者:太空宇宙 更新时间:2023-11-03 18:47:57 25 4
gpt4 key购买 nike

假设我有一些(超过 20 个)变量,我想将它们保存到一个文件中。我不想重复相同的代码 20 次。我写了一个宏,但它给了我一个错误。

我的测试用例:

;-----------------------------------------------
(defn processor [ some-parameters ]

(let [
;after some operation ,got these data:
date-str ["JN01","JN02","JN03","JN04"];length 8760
date-temperature (map #(str %2 "," %1) [3.3,4.4,5.5,6.6] date-str) ; all vector's length are 8760
date-ws (map #(str %2 "," %1) [0.2,0.1,0.3,0.4] date-str) ;
;... many variables such like date-relative-humidity,date-pressure, name starts with "date-",
; all same size
]
;(doseq [e date-temperature]
; (println e))
(spit "output-variable_a.TXT"
(with-out-str
(doseq [e date-temperature]
(println e))))
;same 'spit' part will repeat many times
))

(processor 123)
; I NEED to output other variables(ws, wd, relative-humidity, ...)
; Output example:
;JN01,3.3
;JN02,4.4
;JN03,5.5
;JN04,6.6
;-----------------------------------------------

我想要的是一个可以这样使用的宏/函数:

(write-to-text temperature,ws,wd,pressure,theta-in-k,mixradio)

这个宏/函数将完成这项工作。我不知道如何编写这样的宏/函数。

我的宏贴在这里,但它不起作用:

(defmacro write-array [& rest-variables ]
`(doseq [ vname# '~rest-variables ]
;(println vname# vvalue#)
(println "the vname# is" (symbol vname#))
(println "resolve:" (resolve (symbol (str vname# "-lines"))))
(println "resolve2:" (resolve (symbol (str "ws-lines"))))
(let [ vvalue# 5] ;(var-get (resolve (symbol vname#)))]
;----------NOTE: commented out cause '(symbol vname#)' won't work.
;1(spit (str "OUT-" vname# ".TXT" )
;1 (with-out-str
;1 (doseq [ l (var-get (resolve (symbol (str vname# "-lines"))))]
;1 (println l))))

(println vname# vvalue#))))

我发现问题出在(symbol vname#)部分,这个方法只适用于GLOBAL变量,不能绑定(bind)到date-temperature in LET 形式,(symbol vname#) 返回 nil。

最佳答案

您似乎想使用 let 中的绑定(bind)名称及其值编写一个分隔值文件。宏在编译期间转换代码,因此它们无法知道您传递的符号绑定(bind)到的运行时。您可以使用宏来发出将在运行时评估的代码:

(defmacro to-rows [& args]
(let [names (mapv name args)]
`(cons ~names (map vector ~@args))))

(defn get-stuff []
(let [nums [1 2 3]
chars [\a \b \c]
bools [true false nil]]
(to-rows nums chars bools)))

(get-stuff)
=> (["nums" "chars" "bools"]
[1 \a true]
[2 \b false]
[3 \c nil])

或者,您可以为每行生成一个 HashMap :

(defmacro to-rows [& args]
(let [names (mapv name args)]
`(map (fn [& vs#] (zipmap ~names vs#)) ~@args)))

=> ({"nums" 1, "chars" \a, "bools" true}
{"nums" 2, "chars" \b, "bools" false}
{"nums" 3, "chars" \c, "bools" nil})

然后您需要使用 data.csv 或类似代码将其写入文件。

要查看to-rows 扩展到什么,您可以使用macroexpand。这是在编译时生成的代码,将在运行时评估。它在编译时完成获取符号 names 的工作,但发出将在运行时处理它们的绑定(bind) 的代码。

(macroexpand '(to-rows x y z))
=> (clojure.core/cons ["x" "y" "z"] (clojure.core/map clojure.core/vector x y z))

顺便说一句,我假设您没有在 let 绑定(bind)中键入数千个文字值。我认为这回答了所提出的问题,但可能有比这更直接的方法。

关于variables - 如何在clojure 宏中绑定(bind)var 的名称和值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52270937/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com