Scala File Glob Matcher

Posted 2021-02-21T22:04:20.529516+00:00

Seven years ago I worked for two days on writing a file glob parser function in Scala. I still think about that function every now and then.

I don't really ever write in Scala, but I did a whole project in it once to experience what that would be like. There were a lot of things I learned and took away to other languages I use.

Scala has a lot of increddible features that can make code safe and succinct. However if you're not using it regularly the results of using those feature can be code that is very difficult to understand.

I wrote a file glob parser in Scala that I no longer understand once I look away from it for more than 30 seconds. I think about it around once a year and go back to study it. It is one of my favorite functions in how short it became and how opaque its function is.


Here are the tests that is passes

def testNoAccumulator() {
    assertTrue(globMatch("testFile.js", "testFile.js"))
    assertFalse(globMatch("testFile.js", "testOther.js"))

def testSimpleAccumulator() {
    assertTrue(globMatch("*.js", "testFile.js"))
    assertFalse(globMatch("*.js", "testFile.jsp"))
    assertTrue(globMatch("Test*.scala", "TestDescriptorUtil.scala"))
    assertFalse(globMatch("Test*.scala", ""))

def testComplexAccumulator() {
    assertTrue(globMatch("*.js", "testFile.js.js"))
    assertTrue(globMatch("Test*.Fn*.js", "TestCtrlPass.FnBox.js"))
    assertTrue(globMatch("Test*.Fn*.js", "TestCtrlPass.Fx.FnBox.js"))

And Here is the Function

def globMatch(glob: String, name: String): Boolean = {
    def chM(n: List[Char], g: List[Char]): Boolean =
        n.isEmpty || g.nonEmpty && (
            (n.head == g.head && chM(n.tail, g.tail)) ||
            (g.head == '*' &&
                (chM(n.tail, g.tail)) ||
                (n.length > g.length && chM(n.tail, g))))
    chM(name.toList, glob.toList)
Enter your login credentials.