问题描述
我在理解 scala3 中的 //@ts-check
/// <reference types="c:/Users/USERNAME/.vscode/extensions/ego-digital.vscode-powertools-0.64.0/node_modules/vscode" />
// Allows us to reference the `vscode` module with jsdoc `@type`
async function vscodeⁱ() {if (1 == 1) return null; return import ('vscode')}
exports.execute = async (args) => {
// Allows us to reference the `vscode` module with jsdoc `@type`
const vscode = await vscodeⁱ()
/** @type {vscode} */
const vs = args.require ('vscode')
// NB: The following code is fully typed in VSCode
const windowᵛ = vs.window
const editorᵛ = windowᵛ.activeTextEditor
const start = editorᵛ.selection.start
}
如何替代 scala 2 中的 TypeTest
时遇到问题。用例能够匹配 x: List[Int] 等通用参数。
我试图解决的具体例子:
TypeTag
编译器警告中的编译结果(如预期)
enum Foo :
case Bar()
case Baz()
case class Mod[T <: Foo](modFn: T => T)
def modifyBarsOrBaz(mod: Mod[_]) = mod match
case barMod: Mod[Foo.Bar] => ???
case bazMod: Mod[Foo.Baz] => ???
和一个无法访问的案例。
现在我的问题是:这在 Scala3 中完全可行吗?
我的印象是我必须以某种方式为所有 X 提供一个 the type test for Mod[Foo.Bar] cannot be checked at runtime
,这些 X 是 TypeTest[Any,Mod[Foo.X]]
枚举的子类。
但我什至在努力实现这些测试,以及了解 Foo
需要什么 using
参数才能使其工作。
因此我想出了以下(不起作用)解决方案:
modifyBarsOrBaz
以及一个简单的 tt 实现
def modifyBarsOrBaz[T <: Foo](mod: Mod[T])(using TypeTest[Any,Mod[T]]) = mod match
case barMod: Mod[Foo.Bar] => ???
case bazMod: Mod[Foo.Baz] => ???
我试图在网上搜索答案,但由于这是一个全新的内容,我并不走运。有什么提示吗?
解决方法
这里的问题是 1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:mergeExtDexDebug'.
> Could not resolve all files for configuration ':app:debugRuntimeClasspath'.
> Failed to transform weka-stable-3.8.5.jar (nz.ac.waikato.cms.weka:weka-stable:3.8.5) to match attributes {artifactType=android-dex,dexing-enable-desugaring=true,dexing-incremental-transform=false,dexing-is-debuggable=true,dexing-min-sdk=16,org.gradle.category=library,org.gradle.libraryelements=jar,org.gradle.status=release,org.gradle.usage=java-runtime}.
> No variants of com.github.fommil.netlib:all:1.1.2 match the consumer attributes:
- com.github.fommil.netlib:all:1.1.2:
- Incompatible because this component declares attribute 'artifactType' with value 'pom' and the consumer needed attribute 'artifactType' with value 'android-classes-jar'
- Other compatible attributes:
- Doesn't say anything about dexing-enable-desugaring (required 'true')
- Doesn't say anything about dexing-incremental-transform (required 'false')
- Doesn't say anything about dexing-is-debuggable (required 'true')
- Doesn't say anything about dexing-min-sdk (required '16')
> Failed to transform mtj-1.0.4.jar (com.googlecode.matrix-toolkits-java:mtj:1.0.4) to match attributes {artifactType=android-dex,org.gradle.usage=java-runtime}.
> No variants of com.github.fommil.netlib:all:1.1.2 match the consumer attributes:
- com.github.fommil.netlib:all:1.1.2:
- Incompatible because this component declares attribute 'artifactType' with value 'pom' and the consumer needed attribute 'artifactType' with value 'android-classes-jar'
- Other compatible attributes:
- Doesn't say anything about dexing-enable-desugaring (required 'true')
- Doesn't say anything about dexing-incremental-transform (required 'false')
- Doesn't say anything about dexing-is-debuggable (required 'true')
- Doesn't say anything about dexing-min-sdk (required '16')
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
将能够检查 TypeTest[Any,Mod[T]]
是否是 Any
,而不是检查 Mod[T]
是否是 {{ 1}} 或 Mod[T]
。您需要的是 Mod[Foo.Bar]
和 Mod[Foo.Baz]
:
TypeTest[Any,Mod[Foo.Bar]
我不知道为什么一个简单的 TypeTest[Any,Mod[Foo.Baz]
不能与范围内的 def modifyBarsOrBaz(mod: Mod[?])(using asBar: TypeTest[Any,Mod[Foo.Bar]],asBaz: TypeTest[Any,Mod[Foo.Baz]]) =
mod match
case asBar(barMod) => println("barMod")
case asBaz(bazMod) => println("bazMod")
一起使用,我稍后会谈到。
但是,您现在必须自己实际实现这些 barMod: Mod[Foo.Bar]
。由于 JVM 没有具体化,因此您必须在 TypeTest[Any,Mod[Foo.Bar]]
类中存储有关 TypeTest
的信息。如果你真的想保留 T
一个单一的案例类,你可以这样做:
Mod
Mod
和 type BarOrBaz[T <: Foo] <: String = T match {
case Foo.Bar => "Bar"
case Foo.Baz => "Baz"
}
case class Mod[T <: Foo](modFn: T => T,tag: BarOrBaz[T])
的 TypeTest
实例现在可以通过内联方法提供:
Bar
Baz
将是
import compiletime.constValue
inline given [T <: Foo]: TypeTest[Mod[?],Mod[T]] = new TypeTest:
def unapply(mod: Mod[?]) = Option.when(mod.tag == constValue[BarOrBaz[T]])(mod.asInstanceOf[mod.type & Mod[T]])
为方便起见,可以创建一个内联 modifyBarsOrBaz
方法:
def modifyBarsOrBaz(mod: Mod[?])(using asBar: TypeTest[Mod[Foo],asBaz: TypeTest[Mod[Foo],Mod[Foo.Baz]]) = mod match
case asBar(barMod) => println("barMod")
case asBaz(bazMod) => println("bazMod")
你可以像这样使用它 (Scastie):
apply
但实际上,对这样的类型测试的需求对我来说就像是一种代码味道。我建议重新考虑您的设计以解决它,而不是使用这样的标签。