2016-11-01 3 views
2

я не могу понять, почему неявное преобразование от Scala до значений JS не работает таким образом:Неявные преобразования 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 - сутенер моего типа Xlike this, но я стараюсь избегать этого, потому что это более шаблонный и много больше объектов будет экземпляр во время выполнения таким образом. Независимо от этого, я все еще хочу понять, почему именно мой код не работает.

ответ

2

Причина, по которой вызов map не работает, является ограничением в указателе типа Scala: перед поиском неявных преобразований ему необходимо разрешить полный тип. Однако Scala 2.12 приносит SAM treatement так же, как Java. Примерно это означает, что вы можете написать лямбда вместо анонимного класса, реализующего интерфейс с помощью одного метода.

Так x.map(a => "yo") будет расширяться в:

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

Какой компилятор Scala.js обрабатывает отдельно. Вы можете включить обработку SAM в Scala 2.11 с флагом -Xexperimental.

Причина, по которой звонок create не работает, заключается в отсутствии неявного преобразования (в стандартной библиотеке Scala.js) от Option[T] до js.UndefOr[T]. Там - - неявное преобразование в JSRichOption[T], которое позволяет использовать метод orUndefined. Вы должны написать:

x.create(None.orUndefined) 

Или в этом случае, вы можете просто написать:

x.create(js.undefined) 
Смежные вопросы