Currently, we can create a quoted.Type[X] with
val t1: Type[X] = '[X] // special syntax
val t2: Type[X] = Type[X] // Type.apply method
val t2: Type[X] = summon[Type[X]] // given by Type.apply
the first two are equivalent as '[X] is typed as Type[X] which is just a call to the function Type.apply. Most of the time this type is not generated by hand, it is just summoned for some contextual parameter. Hence the special syntax '[...] is redundant.
On the other side, using a quoted.Type[X] can be done with
def f[X](using QuoteContext)(using t: Type[X]) = '{
val t1: $t = ??? // special syntax
val t2: t.T = ??? // accessed directly
val t3: X = ??? // healed using t.T
}
both are equivalent as '$t is typed as t.T which is just a member selection. Most of the type we use directly X which gets healed to t.T. Hence the special syntax $t is redundant.
Furthermore, we used quotes and splices for both expressions and types because in the beginnings we thought that they behaved similarly level-wise. But now that we realized that this is not true, this similarity in syntax only leads to confusion.
Should we remove this syntax?
Can you manually insert a type evidence you don't have in implicit scope? As in { List.empty[${foo.bar.theType}] }. It feels like not having such a capability might be annoying — you'd have to do something like:
given as foo.bar.T = foo.bar.theType
'{ List.empty[foo.bar.theType.T] }
Obligatory "it works in Squid!":
scala> object foo {
| object bar {
| type T
| val theType = codeTypeOf[Int].asInstanceOf[CodeType[T]]
| }
| }
defined object foo
scala> code"List.empty[${foo.bar.theType}]"
res0: squid.IR.ClosedCode[List[foo.bar.T]] = code"scala.collection.immutable.List.empty[scala.Int]"
Yes. The t.T does that. There we do not need to look for the implicit because we already have it from the t itself. The splice behaves the same way. Though in some cases inference decides to widen them and there we might need it implicitly.
If .T is meant to be a public API, it needs a more descriptive name I think, maybe .Splice or .Repr
@smarter I used to think that too, but this type doesn't really embody anything specific that would warrant a more specific name. One could think a "good" name would be something like UnerlyingType, but that's just verbose and would simply add a lot of needless noise. It's the same reason we don't use ElementType instead of A for collections. In the end, I think theType.T is clear enough and more concise, which actually helps when reading code.
Most helpful comment
@smarter I used to think that too, but this type doesn't really embody anything specific that would warrant a more specific name. One could think a "good" name would be something like
UnerlyingType, but that's just verbose and would simply add a lot of needless noise. It's the same reason we don't useElementTypeinstead ofAfor collections. In the end, I thinktheType.Tis clear enough and more concise, which actually helps when reading code.