3

I am trying to create a function with the variable number of arguments

def foo(args: String*)

What this function does is, it eliminates the empty strings and separate rest of the strings with a comma (,).

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

When I extended this function to support Option[String] arguments

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(", ")
}

I got a warning saying

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

And when I pass arguments

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

I got error

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

How should I create such function supporting Option[String] as well?

Fahad Siddiqui
  • 1,829
  • 1
  • 19
  • 41
  • I got one possible solution https://gist.github.com/fahadsiddiqui/b530a093a643f489a9a661606d479f30, but please let me know if there is an optimal solution. – Fahad Siddiqui Mar 22 '17 at 06:52
  • Also https://stackoverflow.com/questions/16056645/how-to-pattern-match-on-generic-type-in-scala – danielnixon Mar 22 '17 at 07:06
  • Using `Any` is a strong code smell - it's the top of the [Type Hierarchy](docs.scala-lang.org/tutorials/tour/unified…). As a result, the compiler can't help you out, i.e. prevent run-time errors, since the type isn't useful given its broadness. – Kevin Meredith Mar 22 '17 at 18:36

2 Answers2

3

You could use collect and avoid Option altogether:

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

collect is the equivalent of filter combined with map.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
Don Mackenzie
  • 7,953
  • 7
  • 31
  • 32
1

Similar to your solution

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(", ")
}
Fahad Siddiqui
  • 1,829
  • 1
  • 19
  • 41
Binzi Cao
  • 1,075
  • 5
  • 14