Scala 如何实施";“无景观”;在斯卡拉?

Scala 如何实施";“无景观”;在斯卡拉?,scala,Scala,这是我上一篇文章的后续文章 由于这些答案,我意识到escape函数实际上是一个flatMap,带有参数f:Char=>Seq[Char]以将转义字符映射到转义序列(参见答案) 现在我想知道如何实现unescape作为escape的反向操作。我想tt应该与flatMap相反,带有参数f:Seq[Char]=>Char。这有意义吗?您建议如何实施unescape 我想tt应该是一个与flatMap相反的函数,函数为f:Seq[Char]=>Char。这有意义吗 不是真的。您的反函数f:Seq[Cha

这是我上一篇文章的后续文章

由于这些答案,我意识到
escape
函数实际上是一个
flatMap
,带有参数
f:Char=>Seq[Char]
以将转义字符映射到转义序列(参见答案)

现在我想知道如何实现
unescape
作为
escape
的反向操作。我想tt应该与
flatMap
相反,带有参数
f:Seq[Char]=>Char
。这有意义吗?您建议如何实施
unescape

我想tt应该是一个与flatMap相反的函数,函数为f:Seq[Char]=>Char。这有意义吗

不是真的。您的反函数
f:Seq[Char]=>Char
“abc”
上应该返回什么?它应该应用于任何字符序列并返回单个字符。您可以尝试改用
PartialFunction[Seq[Char],Char]
,但会遇到其他问题。您是否将其应用于输入的每个子序列

更通用的解决方案是将
foldLeft
与累加器类型一起使用,累加器类型包含结果的构建部分和转义序列,类似(未测试):

def unescape(str:String)={
val result=str.foldLeft[(String,Option[String])](“”,None)){case((acc,escapedAcc),c)=>
(c,escapedAcc)匹配{
案例('&',无)=>
(acc,部分(“”)
案例(无)=>
(acc+c,无)
案例('&',一些())=>
抛出新的IllegalArgumentException(“嵌套转义序列”)
case(“;”,Some(escapeDataCC1))=>
(acc+unescapeMap(EscapeDataCC1),无)
case(u,Some(escapeDataCC1))=>
(附件,部分(附件1+c))
}
}
结果匹配{
案例(逃逸,无)=>
逃脱
案例(u,部分())=>
抛出新的IllegalArgumentException(“未完成的转义序列”)
}
}
val unescapeMap=Map(“amp”->”和“lt”->”
我想tt应该是一个函数f:Seq[Char]=>Char的flatMap的反面。这有意义吗

不完全正确。您的反函数
f:Seq[Char]=>Char
“abc”
上应该返回什么?它应该应用于任何字符序列并返回单个字符。您可以尝试使用
PartialFunction[Seq[Char],Char]
,但您会遇到其他问题。您是否将其应用于输入的每个子序列

更通用的解决方案是将
foldLeft
与累加器类型一起使用,累加器类型包含结果的构建部分和转义序列,类似(未测试):

def unescape(str:String)={
val result=str.foldLeft[(String,Option[String])](“”,None)){case((acc,escapedAcc),c)=>
(c,escapedAcc)匹配{
案例('&',无)=>
(acc,部分(“”)
案例(无)=>
(acc+c,无)
案例('&',一些())=>
抛出新的IllegalArgumentException(“嵌套转义序列”)
case(“;”,Some(escapeDataCC1))=>
(acc+unescapeMap(EscapeDataCC1),无)
case(u,Some(escapeDataCC1))=>
(附件,部分(附件1+c))
}
}
结果匹配{
案例(逃逸,无)=>
逃脱
案例(u,部分())=>
抛出新的IllegalArgumentException(“未完成的转义序列”)
}
}
val unescapeMap=Map(“amp”->”和“lt”->”
我想tt应该是一个函数f:Seq[Char]=>Char的flatMap的反面。这有意义吗

不完全正确。您的反函数
f:Seq[Char]=>Char
“abc”
上应该返回什么?它应该应用于任何字符序列并返回单个字符。您可以尝试使用
PartialFunction[Seq[Char],Char]
,但您会遇到其他问题。您是否将其应用于输入的每个子序列

更通用的解决方案是将
foldLeft
与累加器类型一起使用,累加器类型包含结果的构建部分和转义序列,类似(未测试):

def unescape(str:String)={
val result=str.foldLeft[(String,Option[String])](“”,None)){case((acc,escapedAcc),c)=>
(c,escapedAcc)匹配{
案例('&',无)=>
(acc,部分(“”)
案例(无)=>
(acc+c,无)
案例('&',一些())=>
抛出新的IllegalArgumentException(“嵌套转义序列”)
case(“;”,Some(escapeDataCC1))=>
(acc+unescapeMap(EscapeDataCC1),无)
case(u,Some(escapeDataCC1))=>
(附件,部分(附件1+c))
}
}
结果匹配{
案例(逃逸,无)=>
逃脱
案例(u,部分())=>
抛出新的IllegalArgumentException(“未完成的转义序列”)
}
}
val unescapeMap=Map(“amp”->”和“lt”->”
我想tt应该是一个函数f:Seq[Char]=>Char的flatMap的反面。这有意义吗

不完全正确。您的反函数
f:Seq[Char]=>Char
“abc”
上应该返回什么?它应该应用于任何字符序列并返回单个字符。您可以尝试使用
PartialFunction[Seq[Char],Char]
,但您会遇到其他问题。您是否将其应用于输入的每个子序列

更通用的解决方案是将
foldLeft
与累加器类型一起使用,累加器类型包含结果的构建部分和转义序列,类似(未测试):

def unescape(str:String)={
val result=str.foldLeft[(String,Option[String])](“”,None)){case((acc,escapedAcc),c)=>
(c,escapedAcc)匹配{
案例('&',无)=>
(acc,部分(“”)
案例(无)=>
(acc+c,无)
案例('&',一些())=>
抛出新的IllegalArgumentException(“嵌套转义序列”)
case(“;”,Some(escapeDataCC1))=>
(acc+unescapeMap(EscapeDataCC1),无)
case(u,Some(escapeDataCC1))=>
(acc,部分(esca)
def unescape(str: String) = {
  val result = str.foldLeft[(String, Option[String])](("", None)) { case ((acc, escapedAcc), c) => 
    (c, escapedAcc) match {
      case ('&', None) =>
        (acc, Some(""))
      case (_, None) =>
        (acc + c, None)
      case ('&', Some(_)) =>
        throw new IllegalArgumentException("nested escape sequences")
      case (';', Some(escapedAcc1)) => 
        (acc + unescapeMap(escapedAcc1), None)
      case (_,  Some(escapedAcc1)) =>
        (acc, Some(escapedAcc1 + c))
    }
  }

  result match {
    case (escaped, None) =>
      escaped
    case (_, Some(_)) => 
      throw new IllegalArgumentException("unfinished escape sequence")
  }
}

val unescapeMap = Map("amp" -> "&", "lt" -> "<", ...)
val sb = new StringBuilder
scala.xml.Utility.unescape("amp", sb)
println(sb.toString) // prints &
scala.xml.Utility.unescape("amp", new StringBuilder).toString // returns "&"