理由
根据我的经验,观察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上boxed算术的复杂性。这也是一个令人愉悦的平台无关的解决方案,CLJS可以公开match-number。
问题/替代方案
- 函数应该返回原始值还是boxed值?
- 如何处理像"0xff"这样的字符串?parseFoo函数家族拒绝这些,但0xff可以被Clojure读取器读取。
- 另一方面,decode函数家族处理一些前缀,但它们返回boxed值。但它们也接受像#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部分的解析支持。