目前,我正在尝试解析Scala中的Reader[Token]
。因此,我想在解析步骤中检查Token
是否是特定类的元素(例如AToken
)。
我可以使用以下代码轻松完成:
def aToken = acceptIf(_.isInstanceOf[AToken])("Token " + _ + " is not of type AToken")
^^ { _.asInstanceOf[AToken] }
这完全没问题。但我有几种类型需要检查。因此,对于每种类型,我都需要再次将上述内容写入上面。
所以我想要一些抽象的acceptIfInstanceOf[T]
方法,它会自动(神奇地?)为类型T
创建一个方法。
我目前的解决方案仍然分为两步:
def acceptIfInstanceOf[T](implicit m: Manifest[T]) : Parser[Elem] =
acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m)
def aToken = acceptIfInstanceOf[AToken] ^^ { _.asInstanceOf[AToken] }
这也有效,但我想摆脱aToken
中的函数应用程序,并将其直接包含在acceptIfInstanceOf
中。
可悲的是,这不起作用:
def acceptIfInstanceOf[T](implicit m: Manifest[T]) : Parser[T] =
acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m)
^^ { m.runtimeClass.cast(_) }
我从Scala编译器收到以下错误消息:
scala: type mismatch;
found : _$1 where type _$1
required: T
def acceptIfInstanceOf[T](implicit m: Manifest[T]): Parser[T] =
acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m)
^^ { m.runtimeClass.cast(_) }
^
有人知道是否以及如何构建这样的东西? 谢谢!
答案 0 :(得分:1)
使用_.asInstaceOf[T]
代替m.runtimeClass.cast(_)
,huynhjl解决了最初的问题:
def acceptIfInstanceOf[T](implicit m: Manifest[T]) : Parser[T] =
acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m)
^^ { _.asInstanceOf[T] }
但是,检查_.getClass == m.runtimeClass
显然忽略了_.isInstanceOf
包含的所有子类型语义 - 只是因为我们检查了两个Class
对象的相等性。
如果我想维护isInstanceOf
的语义,我必须使用以下测试:
reflect.ClassManifest.singleType(_) <:< m
但由于这在2.10中已弃用,我将Manifest
替换为TypeTag
并立即使用以下内容:
def acceptIfInstanceOf[T](implicit tag: TypeTag[T]): Parser[T] =
acceptIf(currentMirror.reflect(_).symbol.toType <:< typeOf[T])
("" + _ + " is not of type " + tag.tpe)
^^ { _.asInstanceOf[T] }
我在Stack Overflow上从another question获得了上述解决方案。