理由
根据我自己的经验和观察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
。
然后人们可以使用各种强制转换函数来获取他们所需的精度。这可能更适合此故障报告的理由,即使非常常见的“玩具程序”操作对初学者来说更加平滑,并且匹配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版本增加了支持解析CharSequence的一部分。