Daniel Barclay
unread,Jul 24, 2016, 9:28:48 PM7/24/16Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Sign in to report message
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to scala-user
Can the declared type of a variable (val or var) affect the type
of the expression used to initialize or assign to the variable?
I thought that if I declared a method (somewhat) like this:
def getViaTag[C](implicit classTag: ClassTag[C]): C = ...
and declared/initialized a variable like this:
val v: SpecificClass = getViaTag
then the type of that initialization expression "getViaTag" would
be SpecificClass (because that's what that type has to be to for
the assignment to be valid (and because getViaTag is generic
enough to return type SpecificClass)).
However, when I try that, the method only gets the class tag for
type Nothing, implying that the type of that initialize expression
is just Nothing.
Was I confused in thinking that type inference could propagate the
declared type of variables "down" into some initialization
expressions (not just up from the expressions to the variables)?
Or am I just not using type tags the right way?
Thanks,
Daniel
P.S. Here is my full example code:
package com.us.dsb.explore.tags
import scala.reflect.ClassTag
object TryInferringFromContext {
class GeneralThing
case class SpecificThingOne() extends GeneralThing
case class SpecificThingTwo() extends GeneralThing {
def someMethod(): Unit = {}
}
val things: List[GeneralThing] = List(SpecificThingOne(), SpecificThingTwo())
//import System.err.println
def getThingViaTags[C <: GeneralThing](implicit classTag: ClassTag[C]): Option[C] = {
println(s"classTag = $classTag")
val requestedClass = classTag.runtimeClass
val anyFirstMatch = things.filter(obj => requestedClass.isInstance(obj)).headOption
anyFirstMatch.map(o => o.asInstanceOf[C])
}
def main(args : Array[String]): Unit = {
// As expected/wanted, passed class tag is for SpecificThingOne:
val v1 /*: Option[SpecificThingOne]*/ = getThingViaTags[SpecificThingOne]
// Not as expected/wanted, passed class tag is for Nothing:
val v2: Option[SpecificThingOne] = getThingViaTags
// Why is getThingViaTags's C inferred to be type Nothing?
// Does type inference ever propagate the declared type _from_ a type
// ascription on a variable declaration "down" _to_ the initialization
// expression? If it does, why doesn't it do so here?
// Not as expected/wanted, class class tag is for Nothing:
def takesSpecificType(arg: Option[SpecificThingTwo]): Unit = {}
val v3 = takesSpecificType(getThingViaTags)
}
}