我想在scala.js中使用Numeric。我需要在一些函数中使用Numeric implicity(我添加了scala.js已经拥有它的库)。例如,对于此代码:
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
@JSExportTopLevel("NumericOps")
class JsNumericOps[V] {
@JSExport("add")
def add(x: V, y: V)(implicit num: Numeric[V]): V = {
num.plus(x, y)
}
}
class NumericOps[V: Numeric] {
def add(x: V, y: V)(implicit num: Numeric[V]): V = {
num.plus(x, y)
}
}
之后我在javascript控制台中运行它:
NumericOps().add(3,3)
并得到错误:
scalajsenv.js:211 Uncaught $ c_sjsr_UndefinedBehaviorError {s $ 1:“An 检测到未定义的行为:undefined不是。的实例 scala.math.Numeric“,e $ 1:$ c_jl_ClassCastException,stackTrace $ 1: null,stackdata:$ c_sjsr_UndefinedBehaviorError,stack:“Error↵at $ c_sjsr_UndefinedBehaviorError。$ c_jl_ ... ndpit-fastopt.js:1188:15)↵at :1:14" }
在scala.js中使用Numeric [T] implicity的正确方法是什么?
答案 0 :(得分:2)
如果您没有与JavaScript互操作,那么您对implicit Numeric[T]
的使用会有意义。在Scala代码中,implicits与Scala中的工作方式相同。但是当与JavaScript互操作时,隐式参数变为完全显式:JavaScript没有具有隐式解析的类型检查器来填充缺少的参数,因此甚至需要在JS中的调用站点提供隐式参数。 / p>
显然,这不是你想要的。实际上,除非您导出对Numeric
的相关实例的引用,否则JavaScript代码甚至无法将它们作为参数传递。
相反,您只需要导出不需要Numeric[T]
参数的方法,这意味着您需要为所有可能的JS数字类型重载您的方法add
。不过,你很幸运:JS只有一个 number
类型,它在Scala.js中转换为Double
。因此,您只需要处理Double
中的JsNumericOps
:
@JSExportTopLevel("NumericOps")
class JsNumericOps {
@JSExport
def add(x: Double, y: Double): Double = {
x + y
}
}
同时保持NumericOps
通用和相关的Numeric
暗示。
如果您想重用NumericOps
中JsNumbericOps
的实施,您可以非常轻松地执行此操作:
@JSExportTopLevel("NumericOps")
class JsNumericOps {
private val numericOps = new NumericOps
@JSExport
def add(x: Double, y: Double): Double = {
numericOps.add(x, y)
}
}
此处,Scala编译器会在implicit Numeric[Double]
内推断需要提供给numericOps.add(x, y)
的{{1}}。 JavaScript代码永远不需要看到它,这是JsNumericOps.add
。