Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change a if-else-construct in a more functional style?

is it possible to change this if-else-construct in a more functional style of Scala?

def getMIMEType(document: String): String = {

  if (document.endsWith(".pdf")) {
    return "application/pdf"
  } else if (document.endsWith(".dxf")) {
    return "application/dxf"
  } else if (document.endsWith(".jpg")) {
    return "image/jpeg"
  } else return "application/octet-stream"
}

I tried to use pattern matching, but it doesn't work. So I be curious for a good solution.

like image 852
Twistleton Avatar asked Nov 02 '11 16:11

Twistleton


2 Answers

MIME-Type mapping

I agree with @glowcoder. I find that at least in this particular case it's better to have MIME-Types mapping. Here is a Scala version:

val MimeTypesMapping = Map(
  ".pdf" -> "application/pdf",
  ".dxf" -> "application/dxf",
  ".jpg" -> "image/jpeg"
)

def extension(fileName: String) = fileName substring (fileName lastIndexOf ".")

def getMIMEType(document: String) =
  MimeTypesMapping get extension(document) getOrElse "application/octet-stream"

Also, as Rex Kerr noted, you can add default value directly to the mapping definition:

val MimeTypesMapping = Map(
  ".pdf" -> "application/pdf",
  ".dxf" -> "application/dxf",
  ".jpg" -> "image/jpeg"
) withDefaultValue "application/octet-stream" 

and then use it like this: MimeTypesMapping(extension(document))

Pattern Matching

If you don't like first solution, then you can use pattern matching instead:

def getMIMEType(document: String) = extension(document) match {
  case ".pdf" => "application/pdf"
  case ".dxf" => "application/dxf"
  case ".jpg" => "image/jpeg"
  case _      => "application/octet-stream"
}

Advantage of this solution is that you can can more sophisticated logic in the conditions like for example:

def getMIMEType(document: String) = extension(document) match {
  // ...
  case ".jpg" | ".jpeg" => "image/jpeg"
  // ...
}

Pattern Matching with Custom Extractor

There is also another way to use pattern matching. You can write your own extractor for the file extension an then use it in match:

object Extension {
  def unapply(fileName: String): Option[String] = {
    val idx = fileName lastIndexOf "."

    if (idx != -1) Some(fileName substring idx) else None
  }
}

def getMIMEType(document: String) = document match {
  case Extension(".pdf") => "application/pdf"
  case Extension(".dxf") => "application/dxf"
  case Extension(".jpg") => "image/jpeg"
  case _                 => "application/octet-stream"
}
like image 149
tenshi Avatar answered Nov 13 '22 06:11

tenshi


I don't know exactly what scala's built in structures are, but it sounds like you want a map. Like, Java uses

val map = scala.collection.mutable.HashMap[String, String]()
map.put(".pdf","application/pdf");
map.put(".dxf","application/dxf");
map.put(".jpg","image/jpeg");

Then in your function you use

def ext = getExtension(document); // assume this exists, eh?
if(map.containsKey(ext)) return map.get(ext);
return "application/octet-stream";

Update: It looks like Scala uses a map that's very similar:

http://www.scala-lang.org/api/rc/scala/collection/mutable/Map.html

like image 40
corsiKa Avatar answered Nov 13 '22 07:11

corsiKa