Scala.js中的数字隐含

时间:2018-03-15 10:13:29

标签: scala implicit scala.js

我想在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的正确方法是什么?

1 个答案:

答案 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暗示。

如果您想重用NumericOpsJsNumbericOps的实施,您可以非常轻松地执行此操作:

@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

的实现细节