是否可以在 Scala JS 中创建类型安全的库以供使用 from JavaScript?
Is it possilble to a create type-safe library in ScalaJS for using from JavaScript?
如果是怎么办?在我的最后一个问题中,我询问了为什么这个片段会崩溃:
@JSExport("Test") object TestScalaJs {
@JSExport def callMe[A: ClassTag](f: js.Function1[Int, A]): Array[A] = Array(f(4))
}
在:
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
回复是因为我缺少 callMe
的隐式参数。我之前没有想到这一点,因为 Scala 自动神奇地提供了它,所以这只是第一次尝试:
object TestVanilla {
def callMe[A: ClassTag](f: Int => A): Array[A] = Array(f(4))
}
val res = TestVanilla.callMe(_ + "x");
println(res.mkString(", "));
问题是:
如何编写类型安全的(至少在编译时,不需要动态检查)使用 Scala 的普通功能的库像整数、数组、函数、泛型和 ScalaJS 中的 ClassTag
s,然后可以很容易地*从 JavaScript? 使用,我真的希望这是可能的。
*:我的意思是没有神秘的要求,例如从 JavaScript.
手动构建 ClassTag
s
您可能想在示例中使用 js.Array
:
@JSExport("Test") object TestScalaJs {
@JSExport def callMe[A](f: js.Function1[Int, A]): js.Array[A] = js.Array(f(4))
}
Array
是一个 Scala / Java 风格的数组并且从 JavaScript 中是不透明的(即在它上面做任何事情都是未定义的行为)。 js.Array
是一个 JavaScript 数组,您实际上可以从 JavaScript 使用它。与大多数 Scala 集合一样,它不需要构造 ClassTag
。
如果是怎么办?在我的最后一个问题中,我询问了为什么这个片段会崩溃:
@JSExport("Test") object TestScalaJs {
@JSExport def callMe[A: ClassTag](f: js.Function1[Int, A]): Array[A] = Array(f(4))
}
在:
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
回复是因为我缺少 callMe
的隐式参数。我之前没有想到这一点,因为 Scala 自动神奇地提供了它,所以这只是第一次尝试:
object TestVanilla {
def callMe[A: ClassTag](f: Int => A): Array[A] = Array(f(4))
}
val res = TestVanilla.callMe(_ + "x");
println(res.mkString(", "));
问题是:
如何编写类型安全的(至少在编译时,不需要动态检查)使用 Scala 的普通功能的库像整数、数组、函数、泛型和 ScalaJS 中的 ClassTag
s,然后可以很容易地*从 JavaScript? 使用,我真的希望这是可能的。
*:我的意思是没有神秘的要求,例如从 JavaScript.
手动构建ClassTag
s
您可能想在示例中使用 js.Array
:
@JSExport("Test") object TestScalaJs {
@JSExport def callMe[A](f: js.Function1[Int, A]): js.Array[A] = js.Array(f(4))
}
Array
是一个 Scala / Java 风格的数组并且从 JavaScript 中是不透明的(即在它上面做任何事情都是未定义的行为)。 js.Array
是一个 JavaScript 数组,您实际上可以从 JavaScript 使用它。与大多数 Scala 集合一样,它不需要构造 ClassTag
。