Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rewrite this code in Scala using a Functional Programming approach

Below is code snippet that does some URL normalization. How to rewrite it to use immutable variables only?

Of course, without making it larger or more complex.

private def normalizeUrl(url0: String) = {
  var url = url0

  if (url.endsWith("/")) {
    url = url.dropRight(1)
  }

  if (url.indexOf(':') < 0 || 
      url.indexOf(':') == 1) { //windows absolute path
    url = "file:" + url;
  }

  url = url.replaceAll("\\\\", "/");

  url
}
like image 794
Sergey Alaev Avatar asked Nov 29 '22 10:11

Sergey Alaev


2 Answers

If you wanted to chain a bunch of these if/then conditions together to modify a string you could consider adding an implicit class to handle the if/then evaluations like so:

object UrlPimping{
  implicit class PimpedUrl(val url:String) extends AnyVal{
    def changeIf(condition:String => Boolean)(f:String => String):String = {
      if (condition(url)) f(url)
      else url      
    }
  }
}

private def normalizeUrl(url: String) = {
  import UrlPimping._

  url.
    changeIf(_.endsWith("/"))(_.dropRight(1)).
    changeIf(u => u.indexOf(':') < 0 || u.indexOf(':') == 1)(u => s"file:$u").
    replaceAll("\\\\", "/")
}

This would be overkill if you only had these two conditions to evaluate, but might be nice if you had more and this was a common pattern.

like image 68
cmbaxter Avatar answered Dec 05 '22 05:12

cmbaxter


Consider name of functional programming! The whole point is that you replace variables with functions.

private def normalizeProtocol(url: String) = 
   if (url.endsWith("/")) url.dropRight(1) else url

private def removeEndingSlash(url: String) = 
  if (url.indexOf(':') < 0 || 
    url.indexOf(':') == 1)  //windows absolute path
    "file:" + url
  else 
    url

private def replaceSlash(url: String) = 
  url.replaceAll("\\\\", "/");

private def normalizeUrl(url: String) = 
  replaceSlash(normalizeProtocol(removeEndingSlash(url)))

CM Baxter points out, the last function could also be written as

private val normalizeUrl = 
   removeEndingSlash _ andThen 
   normalizeProtocol andThen 
   replaceSlash

I leave it to you to decide which is more legible.

like image 38
Michael Lorton Avatar answered Dec 05 '22 04:12

Michael Lorton