理由
基于我的个人经验,以及观察 Slack 中的新手频道,一个初学者最常见的坑就是如何将字符串解析为整数。
这以多种方式出错
- 人们发现了
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 版本增加了对解析 CharSequence 部分的支持。