如何在Clojure中扩展数值协议

7
我正在尝试使用协议来创建一个工程数字类型(“knumber”),这样我就可以说(+ "1k" "2Meg"),并得到类似于"2.001Meg"的结果。我应该能够像这样从knumber中获取浮点值:(:val my-knumber),但通常打印机应该显示字符串,也可以通过以下方式访问:(:string my-knumber)。这个数字将支持所有常见的p、n、u、m、k、Meg、G后缀,并在它们之间自动转换,例如(/ "1Meg" "1G") -> "1m")。我希望能够将其传递给任何期望数字的函数。
无论如何,有人可以为此提供一种策略吗?我认为我需要使用协议。我目前有一个(defrecord knumber [val string]),但我不确定接下来要做什么。
Clojure数字满足哪些协议?我想我需要扩展一些现有的协议/接口来实现这一点。
谢谢

我知道这不是同一件事,但你可以使用科学计数法:(/ 1e6 1e9) - DaoWen
2个回答

4
我认为你的策略应该如下所示:
  • 将记录KNumber定义为类似于(defrecord knumber [value unit-map])
  • unit-map作为单位到整数幂的映射(如果这些是工程数字,您将需要像m/s^2这样的单位,对吗?)。它可能看起来像{"m" 1 "s" -2}
  • KNumber实现java.lang.Number,以便您可以将其与Clojure中已经存在的其他数学函数一起使用。您将需要实现doubleValuelongValue等方法。
  • 定义一个协议NumberWithUnits,您可以将其扩展到KNumber和普通Clojure数字上。至少它应该有方法(numeric-value [number])(get-units [number])
  • 然后在您自己的命名空间中定义您的数学函数+*-等,它们操作任何实现NumberWithUnits协议并返回KNumber的内容。
  • 关于不同的单位比例(例如“m”与“km”),我建议标准化每种单位类型的内部表示的单一比例(例如距离的“m”),但提供转换到其他单位比例以进行输入/输出目的的选项。

如何让“KNumber”实现“java.lang.Number”的接口? “defprotocol”仅支持实现接口,而Java的“Number”是一个抽象类。 - remvee

0

frinj library 是一个用于单位计算的 Clojure 库。查看源代码可能会给你一些不错的想法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接