理由
根据我的个人经验,以及观察 Slack 中的新手频道,新来者最常见的陷阱之一就是想弄清楚如何将字符串解析为 int。
这出了很多问题
- 人们发现了
int
函数,其文档字符串是 转换为 int — 如果传递字符串则抛出异常。
- 人们建议使用
Integer/parseInt
,这完成了工作,但不能用作 (map Integer/parseInt coll-of-strings)
— 这令人惊讶,因为他们第一次接触 Java 混合。
- 人们建议使用
#(Integer/parseInt %)
,它执行预期操作,但其语法对于 Clojure 的前 10 分钟来说可能有点多。
- 有时人们建议使用
#(Integer. %)
,这在 Java 11 中已被弃用。
- 在 ClojureScript 中,人们会进行相同的操作,必须选择不同的混合方式来完成此操作。
建议 1
考虑在 Clojure 中添加一个 parse-*
函数系列,它是 Java 混合的薄包装。请参阅附录以获取可能的列表。
建议 2
考虑将 clojure.lang.LispReader.matchNumber
暴露为 parse-number
。
然后人们可以使用不同的强制转换函数来获取他们所需的精度。这可能与票据的理由更吻合,即简化对初学者的非常常见的“玩具程序”操作,并与阅读器的行为匹配将是最令人惊讶的事情。
对于关注性能的人来说,他们已经更了解 JVM 上的装箱算术的复杂性。这也是一个令人愉悦的平台无关的系统,CLJS 可以暴露 match-number
。
问题/替代方案
- 函数应返回原始类型还是装箱值?
- 如何处理类似于
"0xff"
的字符串?parseFoo
函数系列拒绝这些值,但 0xff
可以通过 Clojure 阅读器读取。
- 另一方面,
decode
函数系列处理某些前缀,但返回一个装箱值。但它们也接受像 #10
这样的数字,这是一个无效的 Clojure 字面量。
附录
以下是一个关于原始值返回函数的可能完整列表(截至 JVM 8):
name args ret-value
parse-int s int
parse-int s, radix int
parse-uint s int
parse-uint s, radix int
parse-long s long
parse-long s, radix long
parse-ulong s long
parse-ulong s, radix long
parse-short s short
parse-short s, radix short
parse-byte s byte
parse-byte s, radix byte
parse-float s float
parse-double s double
非签名功能是在 Java 8 中添加的,因此可以在较新的 Clojure 版本中安全使用。较新的 JVM 版本添加了对字符序列部分解析的支持。