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

如何使用函数式编程方法在Scala中重写此代码,scala,functional-programming,Scala,Functional Programming,下面是进行URL规范化的代码片段。如何将其重写为仅使用不可变变量 当然,不要让它变得更大或更复杂 private def normalizeUrl(url0: String) = { var url = url0 if (url.endsWith("/")) { url = url.dropRight(1) } if (url.indexOf(':') < 0 || url.indexOf(':') == 1) { //windows absolu

下面是进行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
}
private-def-eurl(url0:String)={
var url=url0
if(url.endsWith(“/”){
url=url.dropRight(1)
}
if(url.indexOf(':')<0 | |
url.indexOf(':')==1{//windows绝对路径
url=“文件:”+url;
}
url=url.replaceAll(“\\\”,“/”);
网址
}

例如,考虑一种具有中间结果的直观方法,以及
if-else
表达式

private def normalizeUrl(url0: String) = {
  val url1 = 
    if (url0.endsWith("/")) url0.dropRight(1) 
    else url0
  val url2 = 
    if (url1.indexOf(':') < 0 || url1.indexOf(':') == 1) "file:" + url1
    else url1

  url2.replaceAll("\\\\", "/")
}
private-def-eurl(url0:String)={
val url1=
if(url0.endsWith(“/”)url0.dropRight(1)
else url0
val url2=
如果(url1.indexOf(“:”)<0 | | url1.indexOf(“:”)==1)“文件:“+url1”
else url1
url2.replaceAll(“\\\”,“/”)
}

注意,最后一个表达式,
url2
with
replaceAll
,将被返回。

一些重构和链接如何?此处不需要您的
var url

我认为这是可行的:

private def normalizeUrl(url: String) = {
  (if (url.indexOf(':') < 0 || url.indexOf(':') == 1) {
    "file:"
  } else {
    ""
  }) + (if (url.endsWith("/")) {
    url.dropRight(1)
  } else {
    url
  }).replaceAll("\\\\", "/")
}
private-def-eurl(url:String)={
(如果(url.indexOf(':'))<0 | url.indexOf(':')==1){
“文件:”
}否则{
""
})+(如果(url.endsWith(“/”)){
url.dropRight(1)
}否则{
网址
}).replaceAll(“\\\”,“/”)
}
当然,为了更好的可读性,我建议使用如下内容:

private def normalizeUrl(url: String) = {
  val prefix  = if (url.indexOf(':') < 0 || url.indexOf(':') == 1) "file:" else ""
  val noSlash = if (url.endsWith("/")) url.dropRight(1) else url

  (prefix + noSlash).replaceAll("\\\\", "/")
}
private-def-eurl(url:String)={
val prefix=if(url.indexOf(“:”)<0 | | url.indexOf(“:”)==1)文件:“else”
val noSlash=if(url.endsWith(“/”)url.dropRight(1)else url
(前缀+noSlash).replaceAll(“\\\\”,“/”)
}

不要害怕使用多个val.:)

> P>如果您想将这些I/SH条件串起来修改字符串,可以考虑添加一个隐式类来处理I/Stand评价,例如:
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("\\\\", "/")
}
object-urlping{
隐式类PimpedUrl(val-url:String)扩展了AnyVal{
def changeIf(条件:String=>Boolean)(f:String=>String):String={
if(条件(url))f(url)
其他网址
}
}
}
private-def-eurl(url:String)={
导入URLPING_
网址。
changeIf(u.endsWith(“/”)(u.dropRight(1))。
changeIf(u=>u.indexOf(“:”)<0 | | u.indexOf(“:”)==1)(u=>s“文件:$u”)。
replaceAll(“\\\”,“/”)
}

如果您只需要评估这两个条件,这将是过分的,但是如果您有更多的条件,并且这是一个常见的模式,这可能会很好

这是另一个。您可以编写测试来达到您的功能(
removeEndSlash
removeSlashes
removeSlashes

def normalizeURL(url: String) = {
    def removeEndSlash(u: String): String = if (u.endsWith("/")) u.dropRight(1) else u
    def isFile(u: String): String = {
      val idx = u.indexOf(':')
      if (idx < 0 || idx == 1)
        "file:" + u
      else
        u
    }
    def removeSlashes( u : String ) = u.replaceAll("\\\\", "/")

    removeSlashes(isFile(removeEndSlash(url)))

  }
def normalizeURL(url:String)={
def removeEndSlash(u:String):String=if(u.endsWith(“/”)u.dropRight(1)else u
def isFile(u:字符串):字符串={
val idx=u.indexOf(“:”)
如果(idx<0 | | idx==1)
“文件:”+u
其他的
U
}
def removeSlashes(u:String)=u.replaceAll(“\\\\\”,“/”)
RemoveSlash(isFile(removeEndSlash(url)))
}
考虑函数式编程的名称!关键在于用函数替换变量

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)))

我让您来决定哪个更清晰。

一个选项是使用读卡器Monad并在其上映射函数:

val normalizeUrl: Reader[String, String] = Reader[String, String](s => s)
  .map(url => if (url.endsWith("/")) { url.dropRight(1) } else url)
  .map(url => if (url.indexOf(':') < 0 || url.indexOf(':') == 1) "file:" + url else url)
  .map(url => url.replaceAll("\\\\", "/"))

我想我更喜欢elm的解决方案,而不是在最后将函数嵌套在一起,你可以这样组合它们:
(removeEndingSlash),然后规范化Protocol,然后替换Slash)(url)
val normalizeUrl: Reader[String, String] = Reader[String, String](s => s)
  .map(url => if (url.endsWith("/")) { url.dropRight(1) } else url)
  .map(url => if (url.indexOf(':') < 0 || url.indexOf(':') == 1) "file:" + url else url)
  .map(url => url.replaceAll("\\\\", "/"))
normalizeUrl("some\\\\url")