理由
根据我自己的经验,以及观察 Slack 中的初学者频道,一个对于新手的极其常见的陷阱就是想知道如何将字符串解析为整数。
这可以通过多种方式出错
- 人们发现了
int
函数,其文档字符串为 转换到整数 - 当传递一个字符串时它将引发异常。
- 人们建议
Integer/parseInt
,该函数可以完成任务,但不能用作 (map Integer/parseInt coll-of-strings)
-- 这很令人惊讶,因为他们第一次接触 Java 互操作性。
- 有人建议
#(Integer/parseInt %)
,这符合预期,但其语法对于您的前 10 分钟 Clojure 可能有点过多。
- 有时人们会用
#(Integer. %)
,这在 Java 11 中已被弃用。
- 人们以同样的方式在 ClojureScript 中进行操作,并必须选择不同的互操作方式来完成此操作。
建议 1
考虑在 Clojure 中添加一个 parse-*
家族函数,这些函数是 Java 互操作的一个薄包装。请参见附录,以获取可能列表。
建议 2
考虑将 clojure.lang.LispReader.matchNumber
公开为 parse-number
。
人们可以使用各种转换函数获取他们需要的精度。这可能更符合这个票据的理由,即为了让初学者非常常见的一个“玩具程序”操作更顺畅,并且匹配 Reader 的行为将是最少令人惊讶的事情。
对于性能敏感的人来说,他们应该更多地了解 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 部分的支持。
已在版本 1.11.0-alpha3 中添加了 parse-long、parse-double、parse-boolean 和 parse-uuid,并在注释中说明: