2016-09-03 4 views
2

я следующий код в Scala, и это работает прекрасно:Scala.js и ClassTag приводит к аварии

object TestVanilla { 
    def callMe[A: ClassTag](f: Int => A): Array[A] = Array(f(4)) 
} 

val res = TestVanilla.callMe(_ + "x"); 
println(res.mkString(", ")); 

Результат:

4x 

полный код: http://scalafiddle.net/console/20337e889ee17ca9862a8317918ae5d9

я переписал его ScalaJS, но, похоже, он разбился по тегу:

@JSExport("Test") object TestScalaJs { 
    @JSExport def callMe[A: ClassTag](f: js.Function1[Int, A]): Array[A] = Array(f(4)) 
} 

вызовов от JS:

var res = Test().callMe(function(x) {return x + 'x';}); 
console.log('TestScalaJs:', res.join(', ')); 

Крушения:

$c_jl_Throwable.fillInStackTrace__jl_Throwable @ VM153:4161 
$c_sjsr_UndefinedBehaviorError.fillInStackTrace__jl_Throwable @ VM153:9241 
$c_jl_Throwable.init___T__jl_Throwable @ VM153:4177 
$c_sjsr_UndefinedBehaviorError.init___T__jl_Throwable @ VM153:9248 
$c_sjsr_UndefinedBehaviorError.init___jl_Throwable @ VM153:9244 
$throwClassCastException @ VM153:196 
$as_s_reflect_ClassTag @ VM153:7824 
$c_LTestScalaJs$.callMe @ VM153:2061 
(anonymous function) @ VM155:2 
$s_Lscalatags_jsdom_Frag$class__applyTo__Lscalatags_jsdom_Frag__Lorg_scalajs_dom_raw_Element__V @ VM153:1108 
$c_Lscalatags_JsDom$TypedTag.applyTo__O__V @ VM153:9981 
$c_Lfiddle_Fiddle$.println__sc_Seq__V @ VM153:2113 
$c_LScalaFiddle$.init___ @ VM153:2021 
$m_LScalaFiddle$ @ VM153:2034 
(anonymous function) @ VM154:1 
(anonymous function) @ VM77 resultframe?theme=light:32 

полный код: https://beetta.scalafiddle.io/sf/YzdMmU/1

Scala.js не поддерживает ClassTag сек? Или я делаю что-то неправильно?


EDIT2: Создано follow up question. На это дан ответ, хотя он на самом деле ничего не решал для меня - мой плохой, я спросил плохо.

Не отвечайте на EDIT1 здесь, пожалуйста, а скорее в следующем вопросе.

EDIT1: Я не прояснил ситуацию. Код - это упрощенная проблема из крошечной библиотеки, которую я хотел написать в ScalaJS, и библиотека предназначена для использования с JavaScript. Я ищу способ решить эту довольно тривиально выглядящую проблему - создание массива, защищенного типом, и в то же время позволяя JS действительно иметь возможность легко вызвать метод. Может быть, какой-то прокси-фасад можно использовать?

ответ

3

Scala.js поддерживает ClassTag с. Ваша проблема в том, что вы ожидаете, что JavaScript заполнит неявные параметры Scala, чего он не может сделать. Ваш метод определения

@JSExport def callMe[A: ClassTag](f: js.Function1[Int, A]): Array[A] = Array(f(4)) 

, как обычно в Scala, что эквивалентно

@JSExport def callMe[A](f: js.Function1[Int, A])(implicit ct: ClassTag[A]): Array[A] = Array(f(4)) 

который четко подчеркивает, что есть параметры для callMe. Scala typechecker может автоматически заполнить второй (неявный) параметр, но JavaScript не может этого сделать. Из JavaScript вам необходимо будет явно передать второй параметр.

+0

Итак, не существует ли способа экспортировать эту функцию только с одним параметром из JavaScript? Я, хотя базовые типы, такие как function, array и int, плавно поддерживаются. Похоже, что с точки зрения создания библиотек в ScalaJS для JavaScript явно ограничивается. Возможно ли это? : -/ – monnef

+0

А как передать параметр типа ClassTag [A] из JS? Ну, нам нужно посмотреть на скомпилированный JS-код для этого? – Samar

 Смежные вопросы

  • Нет связанных вопросов^_^