monnef monnef - 2 months ago 17
Scala Question

ScalaJS and ClassTag results in crash

I have following code in Scala and it works fine:

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

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


Result:

4x


full code: http://scalafiddle.net/console/20337e889ee17ca9862a8317918ae5d9

I rewrote it to ScalaJS, but it seems to be crashing on the tag:

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


Call from JS:

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


Crash:

$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


full code: https://beetta.scalafiddle.io/sf/YzdMmU/1

ScalaJS doesn't support
ClassTag
s? Or am I doing something wrong?




EDIT2: Created a follow up question. This one is answered, even though it didn't actually solve anything for me - my bad, I asked poorly.

Don't answer the EDIT1 here please, but rather in the follow-up question.

EDIT1: I didn't make myself clear. The code is a simplified issue from tiny library I wanted to write in ScalaJS and the library is meant to be used from JavaScript. I am looking for a way how to solve this rather trivial looking issue - creation of type-safe array and in a same time allowing JS to actually be able to easily call the method. Maybe some proxy/facade can be used?

Answer

Scala.js does support ClassTags. Your issue is that you're expecting JavaScript to fill in Scala implicit parameters, which it cannot do. Your method definition

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

is, as usual in Scala, equivalent to

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

which clearly highlights that there are 2 parameters to callMe. The Scala typechecker can automatically fill in the second (implicit) parameter, but JavaScript cannot do that. From JavaScript, you would have to explicitly pass the second parameter.

Comments