Clojure 如何在列表中不使用双引号

Clojure 如何在列表中不使用双引号,clojure,Clojure,我的代码中有以下行: (spit path (prn-str job-data)) 它做得很好。首先,列表中的每一项都放在双引号之间 ( ":a" ":b" ":a" ) 我想要的预期结果 ( :a :b :a ) 如何达到预期的效果 提前谢谢 我猜工作数据不是你所期望的 user=> (prn-str '(:a :b :c)) "(:a :b :c)\n" 如果您确实有一个包含类似关键字的字符串的列表,并且希望将其转换为关键字,则可以使用 (map (comp keyword

我的代码中有以下行:

(spit path (prn-str job-data))
它做得很好。首先,列表中的每一项都放在双引号之间

( ":a" ":b" ":a" )
我想要的预期结果

( :a :b :a )
如何达到预期的效果


提前谢谢

我猜工作数据不是你所期望的

user=> (prn-str '(:a :b :c))
"(:a :b :c)\n"
如果您确实有一个包含类似关键字的字符串的列表,并且希望将其转换为关键字,则可以使用

 (map (comp keyword #(subs % 1)) '(":a" ":b" ":c"))
它跳过每个元素的:,然后将其转换为关键字

user=> (prn-str (map (comp keyword #(subs % 1)) '(":a" ":b" ":c")))
"(:a :b :c)\n"
发生了什么事 问题不在于项目本身被放在双引号中,而是它们是字符串(与您期望的关键字相反)

,它最终基于,以“读者可以读取对象的方式”打印对象。这意味着字符串是用双引号打印的,否则读者将无法区分字符串和符号,或者无法读取带有空格的字符串。有关Clojure阅读器的更多信息,请参阅

另一方面,它们的目的是“生产供人类消费的产品”,而不是将字符串放在双引号中。这就是为什么您会看到
prn str
println
之间的输出差异

您可以使用
验证这一点。如果您尝试
(>job data first class)
,答案将是
java.lang.String
clojure.lang.Keyword

以下是一些示例,演示了与关键字和字符串一起使用时打印函数的不同行为:

(def str-job-data '(":a" ":b" ":c"))
(def key-job-data '(:a :b :c))

;; `println` prints both keywords and strings without quotes
(with-out-str (println str-job-data)) ;=> "(:a :b :c)\n"
(with-out-str (println key-job-data)) ;=> "(:a :b :c)\n"

;; `prn-str` prints the strings in quotes but the keywords without quotes
(prn-str str-job-data) ;=> "(\":a\" \":b\" \":c\")\n"
(prn-str key-job-data) ;=> "(:a :b :c)\n"
如何改变它 现在寻找可能的解决方案。如果您希望
作业数据
包含关键字,则正确的修复程序最有可能修改
作业数据
。然而,如果我不知道如何生成
工作数据
,我就无法在这里提供太多指导

如果出于某种原因,您无法修改
工作数据
(例如,如果它是由您不控制的代码生成的),并且您希望在包含类似关键字字符串的位置编写关键字,那么@maxthoursie的建议可能是您的最佳选择。(假设您可以切换到
print
println
,但这可能会对其他对象的打印方式产生不良影响)

如果
作业数据
可能包含关键字字符串以外的对象,则只能在适当时应用该函数

(defn convert-job-data [obj]
  (if (and (string? obj)
           (= (.charAt obj 0) \:))
    (keyword-string->keyword obj)
    obj))

(spit path (prn-str (map convert-job-data job-data)))
当然,如果您正在编写的文件是供人使用的,并且所有关于阅读器的事情都无关紧要,那么您可以轻松地制作自己的
println str

(defn println-str [& more]
  (with-out-str (apply println more)))

(spit path (println-str job-data))
如果I(println作业数据),则打印时不带双引号。在我看来,prn str似乎在项目上添加了引号。但如果没有prn str,它只打印LazySeq,这更糟。:-)
(defn println-str [& more]
  (with-out-str (apply println more)))

(spit path (println-str job-data))