class C {
object O
}
val x: C#O.type = (new C).O // error: ';' expected but '.' found
val y: C#(O.type) = (new C).O // error: identifier expected but '(' found
此类型是否有合法语法?
编辑:
val x: c.O.type forSome { val c: C } = (new C).O
给出
ScalaFiddle.scala:4: error: type mismatch;
found : ScalaFiddle.this.C#O.type
required: c.type#O.type forSome { type c.type <: ScalaFiddle.this.C with scala.this.Singleton{} }
val x: c.O.type forSome { val c: C } = (new C).O
^
因此,Scala编译器了解此类型并将其显示为C#O.type
。在创建语法时,似乎忽略了这种情况。
答案 0 :(得分:3)
<强>概述强>
{ val y = new C; y.O }
?我无法证明它不可能,但至少我想确保我没有尝试就不放弃。 这不是一个真正的答案,而是一个失败的尝试列表,也许是某人 发现它很有趣,也许有人找到了脚本(在第二部分中),用于生成有助于报告其发现的错误消息列表......
尝试记下类型
系统地重写阿列克谢罗曼诺夫看起来最有希望的尝试:
val o: x.O.type forSome { val x: C } = (new C).O
val o: x.type#O.type forSome { val x : C } = (new C).O
val o: t#O.type forSome { type t <: C with Singleton } = (new C).O
使用类型lambda类构造的一些或多或少的非系统尝试:
// boring, does nothing, identity, just to recall lambda-syntax
val o: ({ type R <: c.O.type forSome { val c: C } })#R = (new C).O
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[c.type forSome{val c: C}] = (new C).O
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[A forSome {type A <: C}] = (new C).O
使用嵌套forSome
进行实验:
val o: x.type forSome { val x: c.O.type forSome { val c: C }} = (new C).O
C
中其他类型成员的实验:
class C {
object O
type T = O.type
}
val o: C#T = (new C).O
这实际上是编译,但修改了右侧,所以我猜它不算数:
val o: c.O.type forSome { val c: C } = { val c = new C; c.O }
结论:对我来说不可能。
生成所有错误消息的Bash脚本
要生成所有错误消息(没有文件路径和功能警告),
保存此行上方的帖子部分为
saved_post.txt
,然后在同一目录中运行以下脚本:
免责声明:此脚本实际上会修改文件系统中的文件。在运行之前,请确保您真正理解它的作用,并且确实想要运行它。特别是,它会破坏文件'newCdotO.scala'。
#!/bin/bash
tempFile=newCdotO.scala
inputFile=saved_post.txt
grep -oE "^ *val o:.*$" $inputFile | \
while read codeLine
do
printf '=%.0s' {0..80}
echo ""
echo "" > $tempFile
echo "import scala.language.existentials" >> $tempFile
echo "import scala.language.higherKinds" >> $tempFile
echo "class C { object O; type T = O.type }" >> $tempFile
echo "$codeLine" | tee -a $tempFile
printf -- '-%.0s' {0..80}
echo ""
scala $tempFile 2>&1 | sed 's|^.*error:|error:|g'
done |
awk '{print " "$0}'
这会生成以下错误消息墙(嘿,我已经尝试清理它了!):
=================================================================================
val o: x.O.type forSome { val x: C } = (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
found : this.C#O.type
required: x.O.type forSome { val x: this.C }
val o: x.O.type forSome { val x: C } = (new C).O
^
one error found
=================================================================================
val o: x.type#O.type forSome { val x : C } = (new C).O
---------------------------------------------------------------------------------
error: ';' expected but '.' found.
val o: x.type#O.type forSome { val x : C } = (new C).O
^
one error found
=================================================================================
val o: t#O.type forSome { type t <: C with Singleton } = (new C).O
---------------------------------------------------------------------------------
error: ';' expected but '.' found.
val o: t#O.type forSome { type t <: C with Singleton } = (new C).O
^
one error found
=================================================================================
val o: ({ type R <: c.O.type forSome { val c: C } })#R = (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
found : this.C#O.type
required: AnyRef{type R <: c.type#O.type forSome { type c.type <: this.C }}#R
val o: ({ type R <: c.O.type forSome { val c: C } })#R = (new C).O
^
one error found
=================================================================================
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[c.type forSome{val c: C}] = (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
found : this.C#O.type
required: c.type(in type L)#O.type forSome { type c.type(in type L) <: c.type(in value o) forSome { type c.type(in value o) <: this.C with Singleton } with Singleton }
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[c.type forSome{val c: C}] = (new C).O
^
one error found
=================================================================================
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[A forSome {type A <: C}] = (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
found : this.C#O.type
required: c.O.type forSome { val c: A forSome { type A <: this.C } }
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[A forSome {type A <: C}] = (new C).O
^
one error found
=================================================================================
val o: x.type forSome { val x: c.O.type forSome { val c: C }} = (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
found : this.C#O.type
required: x.type forSome { val x: c.type#O.type forSome { type c.type <: this.C } }
val o: x.type forSome { val x: c.O.type forSome { val c: C }} = (new C).O
^
one error found
=================================================================================
val o: C#T = (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
found : this.C#O.type
required: _1.O.type forSome { val _1: this.C }
val o: C#T = (new C).O
^
one error found
=================================================================================
val o: c.O.type forSome { val c: C } = { val c = new C; c.O }
---------------------------------------------------------------------------------
编辑2018-04-11:
偶然发现了this here in 6.4 of the specification:
对于其他表达式
e
,e.x
的输入方式就像{ val y = e; y.x }
一样,对于一些新名称y
。
描述“not-other”表达式的句子之前的部分似乎是指普通名称和稳定标识符。鉴于规范中的这一条款,我并不完全清楚为什么(new C).O
的输入方式与{val y = new C; y.O}
完全相同,因为在重写之后,有问题的代码
val o: c.O.type forSome { val c: C } = (new C).O
看起来就像我在上述一系列尝试中提出的唯一可行的提案:
val o: c.O.type forSome { val c: C } = { val c = new C; c.O }
推断类型C#O.type
是否真的是一个错误,而c.O.type forSome { val c: C }
是规范规定的类型?我不会到目前为止声称它是一个错误,我对规范中使用的配方不够熟悉。
答案 1 :(得分:1)
对象O
仅存在C
的实例,因此其类型也需要与C
的实例绑定。因此,您无法C#O.type
或C#(O.type)
,但您需要首先拥有C
的实例,例如:
scala> class C { object O }
defined class C
scala> val x = new C
x: C = C@59f95c5d
scala> val y: x.O.type = x.O
y: x.O.type = C$O$@5679c6c6
编辑:Alexey Romanov在下面评论说我的结论不正确,可以通过下面的例子证明:
scala> class B { class A {} }
defined class B
scala> val t = new B
t: B = B@63d4e2ba
scala> val u: B#A = new t.A
u: B#A = B$A@1cd072a9
所以我实际上并不知道为什么B#A
有效,但C#O.type
无效:(