请在Clojure 2024 状态调查中分享您的想法!

欢迎!请查看关于页面获取更多关于这是如何工作的信息。

+27
Clojure
已关闭

理由

根据我自己的经验,以及观察 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,并在注释中说明:

2 答案

+2
by

顺便说一下,我认为我们不太可能为匹配所有 Java 类型添加解析器。但我确实认为应该有一些子集来匹配 reader。

  • 固定精度整数 - 总是返回一个 Long
  • 固定精度浮点数(总是会返回一个 Double)
  • 整数 - 与 reader 匹配 - 根据需要返回 Long/BigInteger
  • 浮点数 - 与 reader 匹配 - 根据需要返回 Double/BigDecimal
  • 数字 - 解析所有数字格式时与 reader 匹配

但需要更多的评估。

by
作为更多的论据,初学者通常会偶然遇到 `read-string` 并使用它。当然,可以完成任务,但会有很多问题,对于一个只想将“10”变成10的初学者来说并不是很明显。
by
yep, absolutely
by
这在很大程度上是人们最常做的Java互操作性操作,也是人们在从事类似Advent of Code这样的练习时最早会遇到的情况。
"parse-*" 命名可能在程序中出现的频率相当高。与 clojure.core 的冲突不是致命的,但确实是一个麻烦。这些新功能是否应该放在 clojure.string 命名空间中,以避免冲突?也许是一个新的命名空间?
所有名称/位置待定。
作为一个正在学习Clojure的新手,这确实是困惑之源。知道这是否计划在未来的版本中解决会很好。
这些函数是在Clojure 1.11中添加的 - parse-long、parse-double、parse-boolean 和 parse-uuid。
0
参考: https://clojure.atlassian.net/browse/CLJ-2451(由 alex+import 报告)
...