如何使用函数式编程方法在Scala中重写此代码

Ser*_*aev 4 functional-programming scala

下面是执行一些URL规范化的代码片段.如何重写它只使用不可变变量?

当然,不要让它更大或更复杂.

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
}
Run Code Online (Sandbox Code Playgroud)

cmb*_*ter 10

如果你想将一堆if/then条件链接起来修改一个字符串,你可以考虑添加一个隐式类来处理if/then评估,如下所示:

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("\\\\", "/")
}
Run Code Online (Sandbox Code Playgroud)

如果你只考虑这两个条件,这将是一种过度杀伤,但如果你有更多的条件可能会很好,这是一个常见的模式.


Mal*_*lio 5

考虑函数式编程的名称!重点是用函数替换变量.

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)))
Run Code Online (Sandbox Code Playgroud)

CM Baxter指出,最后一个函数也可以写成

private val normalizeUrl = 
   removeEndingSlash _ andThen 
   normalizeProtocol andThen 
   replaceSlash
Run Code Online (Sandbox Code Playgroud)

我留给你决定哪个更清晰.

  • 您可以将它们组合在一起,而不是将函数组合在一起,如下所示:`(removeEndingSlash _然后normalizeProtocol andThen replaceSlash)(url)` (2认同)