理由
根据我自己的经验和观察Slack中的初学者频道,初学者一个非常常见的问题是想知道如何将字符串解析为int。
这以多种方式出错
- 人们发现了int函数,其docstring为“转换为int”,如果传入字符串则会抛出异常。
- 有人建议使用Integer/parseInt,它可以完成工作,但不能用作(map Integer/parseInt coll-of-strings),这是令人惊讶的,因为这将是他们第一次接触Java互操作。
- 有人建议使用#(Integer/parseInt %),它执行预期操作,但其语法可能对初学的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版本增加了对解析CharSequence部分的支持。