Scala 3 中特征可以有辅助构造函数吗?

Byt*_*ter 1 scala scala-3

我从辅助类构造函数文章中复制了以下代码,粘贴到 Scastie 中,更改classtrait并将 Scala 版本设置为 3.1.0:

\n
val DefaultCrustSize = 12\nval DefaultCrustType = "THIN"\n\n// the primary constructor\ntrait Pizza (var crustSize: Int, var crustType: String) {\n\n    // one-arg auxiliary constructor\n    def this(crustSize: Int) = {\n        this(crustSize, DefaultCrustType)\n    }\n\n    // one-arg auxiliary constructor\n    def this(crustType: String) = {\n        this(DefaultCrustSize, crustType)\n    }\n\n    // zero-arg auxiliary constructor\n    def this() = {\n        this(DefaultCrustSize, DefaultCrustType)\n    }\n\n    override def toString = s"A $crustSize inch pizza with a $crustType crust"\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是结果。它给出以下错误:

\n
org.scalameta.invariants.InvariantFailedException: invariant failed:\nwhen verifying scala.meta.classifiers.`package`.XtensionClassifiable[scala.meta.Template](templ)(scala.meta.Tree.classifiable[scala.meta.Template]).is[Template.Quasi](Template.this.Quasi.ClassifierClass[scala.meta.Template]).||(templ.stats.forall(((x$9: scala.meta.Stat) => scala.meta.classifiers.`package`.XtensionClassifiable[scala.meta.Stat](x$9)(scala.meta.Tree.classifiable[scala.meta.Stat]).is[Ctor](scala.meta.Ctor.ClassifierClass[scala.meta.Stat]).`unary_!`)))\nfound that scala.meta.classifiers.`package`.XtensionClassifiable[scala.meta.Template](templ)(scala.meta.Tree.classifiable[scala.meta.Template]).is[Template.Quasi](Template.this.Quasi.ClassifierClass[scala.meta.Template]) is false\nand also templ.stats.forall(((x$9: scala.meta.Stat) => scala.meta.classifiers.`package`.XtensionClassifiable[scala.meta.Stat](x$9)(scala.meta.Tree.classifiable[scala.meta.Stat]).is[Ctor](scala.meta.Ctor.ClassifierClass[scala.meta.Stat]).`unary_!`)) is false\nwhere Template = scala.meta.Template$@7759c8f1\nwhere templ = {\n\n    // one-arg auxiliary constructor\n    def this(crustSize: Int) = {\n        this(crustSize, DefaultCrustType)\n    }\n\n    // one-arg auxiliary constructor\n    def this(crustType: String) = {\n        this(DefaultCrustSize, crustType)\n    }\n\n    // zero-arg auxiliary constructor\n    def this() = {\n        this(DefaultCrustSize, DefaultCrustType)\n    }\n\n    override def toString = s"A $crustSize inch pizza with a $crustType crust"\n\n}\n    at org.scalameta.invariants.InvariantFailedException$.raise(Exceptions.scala:19)\n    at scala.meta.Defn$Trait$.internal$247(Trees.scala:432)\n    at scala.meta.Defn$Trait$.apply(Trees.scala:425)\n    at scala.meta.internal.parsers.ScalametaParser.$anonfun$traitDef$1(ScalametaParser.scala:4592)\n    at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n    at scala.meta.internal.parsers.ScalametaParser.traitDef(ScalametaParser.scala:4570)\n    at scala.meta.internal.parsers.ScalametaParser.tmplDef(ScalametaParser.scala:4548)\n    at scala.meta.internal.parsers.ScalametaParser.defOrDclOrSecondaryCtor(ScalametaParser.scala:4201)\n    at scala.meta.internal.parsers.ScalametaParser.nonLocalDefOrDcl(ScalametaParser.scala:4172)\n    at scala.meta.internal.parsers.ScalametaParser$$anonfun$templateStat$1$1.applyOrElse(ScalametaParser.scala:5120)\n    at scala.meta.internal.parsers.ScalametaParser$$anonfun$templateStat$1$1.applyOrElse(ScalametaParser.scala:5114)\n    at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:35)\n    at scala.meta.internal.parsers.ScalametaParser.statSeq(ScalametaParser.scala:5057)\n    at scala.meta.internal.parsers.ScalametaParser.templateStats(ScalametaParser.scala:5130)\n    at scala.meta.internal.parsers.ScalametaParser.templateStatSeq(ScalametaParser.scala:5110)\n    at scala.meta.internal.parsers.ScalametaParser.$anonfun$templateBody$1(ScalametaParser.scala:4945)\n    at scala.meta.internal.parsers.ScalametaParser.inBraces(ScalametaParser.scala:800)\n    at scala.meta.internal.parsers.ScalametaParser.templateBody(ScalametaParser.scala:4945)\n    at scala.meta.internal.parsers.ScalametaParser.templateBodyOpt(ScalametaParser.scala:4953)\n    at scala.meta.internal.parsers.ScalametaParser.template(ScalametaParser.scala:4887)\n    at scala.meta.internal.parsers.ScalametaParser.$anonfun$template$1(ScalametaParser.scala:4906)\n    at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n    at scala.meta.internal.parsers.ScalametaParser.autoPos(ScalametaParser.scala:922)\n    at scala.meta.internal.parsers.ScalametaParser.template(ScalametaParser.scala:4891)\n    at scala.meta.internal.parsers.ScalametaParser.$anonfun$templateOpt$1(ScalametaParser.scala:4931)\n    at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n    at scala.meta.internal.parsers.ScalametaParser.autoPos(ScalametaParser.scala:922)\n    at scala.meta.internal.parsers.ScalametaParser.templateOpt(ScalametaParser.scala:4923)\n    at scala.meta.internal.parsers.ScalametaParser.$anonfun$objectDef$1(ScalametaParser.scala:4682)\n    at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n    at scala.meta.internal.parsers.ScalametaParser.objectDef(ScalametaParser.scala:4674)\n    at scala.meta.internal.parsers.ScalametaParser.tmplDef(ScalametaParser.scala:4558)\n    at scala.meta.internal.parsers.ScalametaParser.topLevelTmplDef(ScalametaParser.scala:4540)\n    at scala.meta.internal.parsers.ScalametaParser$$anonfun$topStat$1.applyOrElse(ScalametaParser.scala:5079)\n    at scala.meta.internal.parsers.ScalametaParser$$anonfun$topStat$1.applyOrElse(ScalametaParser.scala:5067)\n    at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:35)\n    at scala.meta.internal.parsers.ScalametaParser.statSeq(ScalametaParser.scala:5057)\n    at scala.meta.internal.parsers.ScalametaParser.topStatSeq(ScalametaParser.scala:5066)\n    at scala.meta.internal.parsers.ScalametaParser.$anonfun$batchSource$1(ScalametaParser.scala:5297)\n    at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n    at scala.meta.internal.parsers.ScalametaParser.autoPos(ScalametaParser.scala:922)\n    at scala.meta.internal.parsers.ScalametaParser.batchSource(ScalametaParser.scala:5256)\n    at scala.meta.internal.parsers.ScalametaParser.$anonfun$source$1(ScalametaParser.scala:5239)\n    at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n    at scala.meta.internal.parsers.ScalametaParser.autoPos(ScalametaParser.scala:922)\n    at scala.meta.internal.parsers.ScalametaParser.source(ScalametaParser.scala:5238)\n    at scala.meta.internal.parsers.ScalametaParser.entrypointSource(ScalametaParser.scala:5244)\n    at scala.meta.internal.parsers.ScalametaParser.$anonfun$parseSource$2(ScalametaParser.scala:143)\n    at scala.meta.internal.parsers.ScalametaParser.parseRule(ScalametaParser.scala:53)\n    at scala.meta.internal.parsers.ScalametaParser.parseSource(ScalametaParser.scala:143)\n    at scala.meta.parsers.Parse$.$anonfun$parseSource$1(Parse.scala:29)\n    at scala.meta.internal.parsers.ScalametaParser$$anon$264.apply(ScalametaParser.scala:5308)\n    at scala.meta.parsers.Api$XtensionParseDialectInput.parse(Api.scala:25)\n    at scala.meta.parsers.Api$XtensionParseInputLike.parse(Api.scala:14)\n    at com.olegych.scastie.instrumentation.Instrument$.apply(Instrument.scala:199)\n    at com.olegych.scastie.instrumentation.InstrumentedInputs$.apply(InstrumentedInputs.scala:23)\n    at com.olegych.scastie.sbt.SbtProcess$$anonfun$4.applyOrElse(SbtProcess.scala:191)\n    at com.olegych.scastie.sbt.SbtProcess$$anonfun$4.applyOrElse(SbtProcess.scala:177)\n    at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:35)\n    at akka.actor.FSM.processEvent(FSM.scala:707)\n    at akka.actor.FSM.processEvent$(FSM.scala:704)\n    at com.olegych.scastie.sbt.SbtProcess.processEvent(SbtProcess.scala:64)\n    at akka.actor.FSM.akka$actor$FSM$$processMsg(FSM.scala:701)\n    at akka.actor.FSM$$anonfun$receive$1.applyOrElse(FSM.scala:695)\n    at akka.actor.Actor.aroundReceive(Actor.scala:539)\n    at akka.actor.Actor.aroundReceive$(Actor.scala:537)\n    at com.olegych.scastie.sbt.SbtProcess.aroundReceive(SbtProcess.scala:64)\n    at akka.actor.ActorCell.receiveMessage(ActorCell.scala:614)\n    at akka.actor.ActorCell.invoke(ActorCell.scala:583)\n    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:268)\n    at akka.dispatch.Mailbox.run(Mailbox.scala:229)\n    at akka.dispatch.Mailbox.exec(Mailbox.scala:241)\n    at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)\n    at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)\n    at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)\n    at akka.dispatch.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)\n
Run Code Online (Sandbox Code Playgroud)\n

为什么?为什么它在第 1 行之后,这看起来完全没问题,当我删除其余部分时它就被接受了?“不变失败”是否意味着它是编译器中的错误?(在这种情况下,许多其他编译器会在消息中添加鼓励报告的信息。)

\n

主要问题:

\n
    \n
  • 特征中是否允许使用次要(或辅助 \xe2\x80\x93 IIUC 这两个术语,这两个术语显然可以互换使用,意思相同)?
  • \n
  • 如果是这样,如何称呼他们?
  • \n
  • 它们有什么用(或者将会有什么用,或者在另一种实际上有它们的语言中)?
  • \n
\n

Jör*_*tag 5

trait关于参数的文档仅提到trait parameters, not trait constructors:

\n
\n

Scala 3 允许特征具有参数,就像类具有参数一样。

\n
\n

它还链接到原始 SIP 文档以供参考:

\n
\n

有关更多信息,请参阅Scala SIP 25.

\n
\n

SIP-25\xc2\xa0\xe2\x80\x93trait参数中,它显示 [粗体 emphasis mine]:

\n
\n

ClassDeftraits中,我们仍然不允许辅助构造函数.

\n
\n

然而,这个限制并没有体现在语法摘要中,它实际上并没有区分classes 和traits syntactically. So, the restriction is purely one of documentation, not syntax specification.

\n

所以,回答你的问题:

\n
\n

为什么?

\n
\n

因为你的代码在语法上是有效的,但在语义上是无效的,而 ScalaMeta 似乎并不期望这种特定类型的语义无效。

\n
\n

为什么它在第 1 行之后,这看起来完全没问题,当我删除其余部分时它就被接受了?“不变失败”是否意味着它是编译器中的错误?(在这种情况下,许多其他编译器会在消息中添加鼓励报告的内容。)

\n
\n

这显然不是编译器中的错误,因为异常不是在编译器中抛出的,而是在 ScalaMeta 中抛出的。

\n
\n

主要问题:

\n
    \n
  • 特征中是否允许使用次要(或辅助 \xe2\x80\x93 IIUC 这两个术语,这两个术语显然可以互换使用,意思相同)?
  • \n
\n
\n

不可以。SIP-25 明确不允许它们。

\n