【问题标题】:Scala.js implicit conversions don't work... sometimes?Scala.js 隐式转换不起作用......有时?
【发布时间】:2016-11-01 05:54:59
【问题描述】:

我不太明白为什么从 Scala 到 JS 值的隐式转换不能以这种方式工作:

Scala Fiddle

import scala.scalajs.js
import scala.scalajs.js.JSConverters._

trait X extends js.Object {
  def map(f: js.Function1[Int, String]) = js.native
  def mapScala(f: Function1[Int, String]) = js.native // just for demo purpose, this is not really part of type X
  def create(maybe: js.UndefOr[Int]) = js.native
}

def test(x: X) {
  // I want these two lines to compile, but they don't
  x.map(a => "yo") // error: missing parameter type
  x.create(None) // error: type mismatch. Found None.type, required: js.UndefOr[Int]

  // This works, but is too verbose
  x.map((a: Int) => "yo") // only if arg type specified like this
  x.mapScala(a => "yo") // because mapScala expects a Scala Function1
  x.create(JSRichOption(None).orUndefined) // because value is manually converted
}

我是否试图以错误的方式使用隐式转换?类X 的实现是在外部以Javascript 提供的。在我的代码中,我想将原生 Scala 值传递给 X 的方法,我不想每次都手动进行转换。

我知道 Scala.js 有另一种方法 - 拉皮条我的类型 X like this,但我试图避免这种情况,因为它更多样板并且更多对象将在运行时以这种方式实例化。无论如何,我仍然想了解为什么我的代码无法正常工作。

【问题讨论】:

    标签: implicit-conversion scala.js


    【解决方案1】:

    map 调用不起作用的原因是 Scala 类型推断器的限制:它需要在查找隐式转换之前解析完整类型。然而,Scala 2.12 带来了SAM treatement,就像 Java 一样。粗略地说,这意味着您可以编写一个 lambda,而不是使用单个方法实现接口的匿名类。

    所以x.map(a => "yo") 将扩展为:

    // Never (!) write this yourself.
    x.map(new js.Function1[Int, String] {
      def apply(a: Int): String = "yo"
    })
    

    Scala.js 编译器单独处理。您可以使用 -Xexperimental 标志在 Scala 2.11 中启用 SAM 处理。

    create 调用不起作用的原因是没有从 Option[T]js.UndefOr[T] 的隐式转换(在 Scala.js 标准库中)。 JSRichOption[T] 的隐式转换,它启用orUndefined 方法。你应该写:

    x.create(None.orUndefined)
    

    或者在这种情况下,您可以简单地写:

    x.create(js.undefined)
    

    【讨论】:

      猜你喜欢
      • 2018-11-19
      • 1970-01-01
      • 2013-08-11
      • 2015-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多