Removing nested blocks from a string I wrote this function in scala that uses tail recursion to remove nested blocks from a text.

Usage examples:

removeBlocks("123{456}789", "{", "}")                            yields "123789"
removeBlocks("123{a{b{c}b}a}789", "{", "}")                      yields "123789"
removeBlocks("123&lt;div&gt;456&lt;/div&gt;789", "&lt;div&gt;", "&lt;/div&gt;")          yields "123789"
removeBlocks("123&lt;&lt;&lt;div&gt;&lt;&lt;&lt;&lt;/div&gt;&gt;&gt;789", "&lt;div&gt;", "&lt;/div&gt;")      yields "123&lt;&lt;&gt;&gt;789"


This is one of my first attempts in a functional language, and I'm deeply dissatistied with my code. It's too long, too nested, and could probably be made more readable. I'm coming from C# and hope to be forgiven for this bad functional code. I'll be happy to hear how it can be improved.

  def removeBlocks(text: String, startMarker: String, endMarker: String) = {
    val startMarkerSize = startMarker.size
    val endMarkerSize = endMarker.size
    val startMarkerHead = startMarker.head
    val endMarkerHead = endMarker.head

    def removeBlocksAcc(s: String, acc: String, nestingLevel: Int): String =
    if (s.isEmpty) acc
      else {
        val (startMarkerCandidate, tail1) = s.splitAt(startMarkerSize)
        if (startMarkerCandidate == startMarker) 
          removeBlocksAcc(tail1, acc, nestingLevel + 1)
        else {
          val (endMarkerCandidate, tail2) = s.splitAt(endMarkerSize)
          if (endMarkerCandidate == endMarker) 
            removeBlocksAcc(tail2, acc, math.max(nestingLevel - 1, 0))
          else {
            val (safePart, candidate) = s.tail.span(c =&gt; c != startMarkerHead &amp;&amp; c != endMarkerHead)
            if (nestingLevel == 0) 
              removeBlocksAcc(candidate, acc + s.head + safePart, nestingLevel)
            else 
              removeBlocksAcc(candidate, acc, nestingLevel)
          }
        }
      }
    removeBlocksAcc(text, "", 0)
  }
I think you are trying to do some pattern matching on strings.

So I did this:

def escape(s: String): String = Seq("{", "}", "whatever").foldLeft(s)((x, y) =&gt; x.replaceAllLiterally(y, "\\" + y))

def removeBlocks(text: String, open: String, close: String): String = {
    val startReg = (s"${escape(open)}(.*)$$").r
    val endReg = (s"${escape(close)}(.*)$$").r
    val otherText = "(.)(.*)$".r

    @tailrec
    def removeBlocksAux(text: String, acc: String = "", lvl: Int = 0): String = {
        assume((text.length() &gt; 0 || lvl == 0) &amp;&amp; lvl &gt;= 0)
        (text, lvl) match {
            case (startReg(text), lvl)     =&gt; removeBlocksAux(text, acc, lvl + 1)
            case (endReg(text), lvl)       =&gt; removeBlocksAux(text, acc, lvl - 1)
            case (otherText(c, text), 0)   =&gt; removeBlocksAux(text, acc + c)
            case (otherText(c, text), lvl) =&gt; removeBlocksAux(text, acc, lvl)
            case ("", _)                   =&gt; acc
        }
    }
    removeBlocksAux(text)
}


I tried to find a way to define the regular expressions inside the match group, but I failed at that, it may not be a good idea after all, but I would like to have a more compact and efficient representation for it. The escape function should escape all special cases of operators in Scala regex, that sounds boring, so there may be already a method for that.

I'm also not a big fan of having a function inside a function, but I kept that design decision. Finally, I'd simply use parser combinators for this, but I guess that's not the point.