[英]Optional function parameter with generic return type
你将如何实现通过正则表达式解析一些输入并将创建的字符串转换为其他类型的类? 我的方法是:
class ARegex[T](regex:Regex, reform:Option[String => T]){
def findFirst(input:String):Option[T] = {
(regex.findFirstIn(input), reform) match{
case (None, _) => None
case (Some(s), None) => Some(s) // this won't compile because of type mismatch
case (Some(s), Some(fun)) => Some(fun(s))
}
}
}
class BRegex[T](regex:Regex, reform:Option[String => T]) {
def findFirst(input:String) = { //returns Option[Any] - erasure
(regex.findFirstIn(input), reform) match{
case (None, _) => None
case (Some(s), None) => Some(s)
case (Some(s), Some(fun)) => Some(fun(s))
}
}
}
我们可以通过消除reform
类型的Option
部分来解决这个问题,并使用不同的机制来表明我们不想以任何方式改变匹配。 当您不希望更改类型时,此机制将使用identity
作为默认参数或传递标识。
class ARegex[T](regex:Regex, reform:String => T = identity[String](_)){
def findFirst(input:String):Option[T] = {
regex.findFirstIn(input) match{
case None => None
case Some(s) => Some(reform(s))
}
}
}
new ARegex("something".r).findFirst("something else") //returns Option[String]
new ARegex("3".r, {x=>x.toInt}).findFirst("number 3") //returns Option[Int]
好吧,问题是类型不匹配,因为你要返回一个String
或一个T
,当然,它在Any
处是统一的。 你不能说你将返回Option[T]
然后返回Option[String]
。
除此之外,该代码的简化版本是这样的:
class ARegex[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[Any] =
regex findFirstIn input map { s => reform map (_(s)) getOrElse s }
}
但是,您可以返回Option[Either[String, T]]
。 代码如下所示:
class ARegex[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[Either[String, T]] =
regex findFirstIn input map { s => reform map (_(s)) toRight s }
}
为什么改革Option [String => T]而不仅仅是String => T? 如果未传递用于创建所需类型实例的机制,则运行时系统无法实际创建适当的对象。 如果你确实需要传递一个Option [String => T],那么你的第二个案例应该只返回None。
另外,flatMap是你的朋友,并且会给你正确的行为(即如果改革是None,则该方法返回None。
class RegexExtractor[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[T] = reform.flatMap(f => regex.findFirstIn(input).map(f))
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.