理由
基于我的经验,并且在观察 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 版本增加了对 CharSequences 部分的解析支持。