5

tl;博士

如何从 ClojureScript 中的数字派生关键字:

(keyword 22)
;;=> :22 but in fact returns nil.

背景

在我的 ClojureScript/Hoplon 应用程序中,我通过cljs-http发出 HTTP 请求。我收到的部分回复如下所示:

{:companies
  {:22 {:description ... } ; A company.
   :64 {:description ... }
   ...                    }
{:offers
  [{:description ... } ; An offer.
   {:description ... }
   ...                ]

后面的向量中的每个报价:offers都有一个:companyId代表 中的键:companies。一旦我收到响应,我就是reset!一个细胞(类似于原子)query

现在,我想遍历每个报价并调用一个offer-tpl创建相应 HTML 的函数。为此,offer-tpl需要报价本身以及相关公司:

(for [offer (:offers @query)]
  (offer-tpl offer (get-in @query [:companies (keyword (:companyId offer))]))))))

尽管这肯定可以做得更优雅(非常感谢建议),但这get-in不起作用。(:companyId offer)返回一个数字(例如22)但(keyword (:companyId offer))返回nil. 调用(keyword (str (:companyId offer)))可以解决问题,但是没有其他方法可以做到这一点吗?

4

1 回答 1

13

(keyword "22")(keyword (str 22))返回:22

您得到的原因:22可能是因为keywordize-keysJSON 翻译选项。例如:

cljs-http 默认为 jsonp 的关键字化键: https://github.com/r0man/cljs-http/blob/1fb899d3f9c5728521786432b5f6c36d1d7a1452/src/cljs_http/core.cljs#L115 但在这种情况下您可以(并且应该)传入禁用关键字化的标志。

并非 JSON 中的所有键都适合 Clojure 关键字化。例如,JSON 键中的空格是有效的,但在 Clojure 中无效。

请注意,数字关键字可能不正确。 https://clojuredocs.org/clojure.core/keyword#example-542692cec026201cdc326d70 似乎该警告已从当前的 Clojure 网站中删除,所以也许这意味着什么,但我不确定是什么。

http://clojure.org/reference/reader目前声明

关键字 - 关键字类似于符号,除了:它们可以而且必须以冒号开头,例如 :fred。它们不能包含“。” 或命名类。像符号一样,它们可以包含命名空间, :person/name 以两个冒号开头的关键字在当前命名空间中解析: 在用户命名空间中,::rect 被读为 :user/rect

然后

符号以非数字字符开头,可以包含字母数字。

关键字的此定义排除:22:with spaces

关键字函数返回无效输入的结果,但这不是一种认可,这仅仅是因为检查不正确的输入将是 Clojure 核心部分的性能开销。

简而言之,并非所有 JSON 键都转换为关键字,因此keywordize-keys除非您知道键空间和/或这样做会提供一些便利,否则您应该避免使用。

于 2016-08-28T15:47:55.517 回答