2017-03-22 82 views
3

我想创建一个函数的参数Scala的情况下,模式匹配错误[字符串]

def foo(args: String*) 

此功能对什么是变量数,它消除了空字符串和独立的休息带逗号的字符串(,)。

def foo(args: String*) = { 
    args.flatMap { 
    case str if str.isEmpty => None 
    case str => Some(str) 
    }.mkString(", ") 
} 

当我扩展了这一功能,支持Option[String]参数

def foo(args: Any*) = { 
    args.flatMap { 
    case str: String if str.isEmpty => None 
    case str: Option[String] if str.getOrElse("").isEmpty => None 
    case str => Some(str) 
    }.mkString(", ") 
} 

我得到了一个警告说

warning: non-variable type argument String in type pattern Option[String] is unchecked since it is eliminated by erasure

当我传递参数

foo("", "Hello", Some(""), Some("what")) 

我错误

scala.MatchError: Some(what) (of class scala.Some) at $anonfun$makeAddress$1.apply(:12) at $anonfun$makeAddress$1.apply(:12)

我该如何创建支持Option[String]的函数呢?

+0

我得到了一个可能的解决方案https://gist.github.com/fahadsiddiqui/b530a093a643f489a9a661606d479f30,但请让我知道是否有一个最佳的解决方案。 –

+0

也https://stackoverflow.com/questions/16056645/how-to-pattern-match-on-generic-type-in​​-scala – danielnixon

+0

使用'任何'是一个强大的代码气味 - 它是[类型层次结构](docs.scala-lang.org/tutorials/tour/unified...)。因此,编译器无法帮助您,即防止运行时错误,因为该类型在广泛性方面无用。 –

回答

3

你可以使用收集资源,避免选项:

def foo(args: String*): String = { 
    args.collect{case s if ! s.isEmpty => s}.mkString(",") 
} 

收集是过滤地图相结合的等价物。

1

到您的解决方案类似

def foo(args: Any*) = { 
    args.flatMap { 
    case str: String if !str.isEmpty => Option(str) 
    case Some(str:String) if !str.isEmpty => Option(str) 
    case _ => None 
    }.mkString(", ") 
} 
+0

另外,在你的代码中,如果你使用下面的代码,就会出现一个bug: println(foo(“”,“Hello”,Some(null),Some(“what”))) –

+0

不应该是Some str)而不是Option(str)? –

+1

不,一些(str)主要用于模式匹配。问题是Some(null)!= None和Option(null)== None。你可以试试scala REPL。 –