Substituting curly braces for paretheses to make method call feel more like a control abstraction

in Programming in scala 4 edition there is example of substituting curly braces for parentheses

def withPrintWriter(file: File)(op: PrintWriter => Unit) = {
    val writer = new PrintWriter(file)
    try {
        op(writer)
    } finally {
    writer.close()
    }
}
val file = new File("date.txt")

and calling withPrintWriter like this:

withPrintWriter(file) { 
    writer =>writer.println(new java.util.Date) 
}

instead of this:

withPrintWriter(file) (writer =>writer.println(new java.util.Date) )

I wonder what is the point of making that. Doesnt it misguide so the reader may think first that its not a function call but some ordinary control structure

I wonder what is the point of making that. Doesn’t it misguide so the reader may think first that its not a function call but some ordinary control structure?

Partly that is a reason, to create DSLs (whenever or not that is a good idea is open to debate).

However, there is a very important reason, blocks can have multiple lines.

// This compiles
withPrintWriter(file) { writer =>
  foo
  bar
  writer.println(new java.util.Date) 
}

// This won't compile
withPrintWriter(file)( writer =>
  foo
  bar
  writer.println(new java.util.Date) 
)

// You would need to do this:
withPrintWriter(file)({ writer =>
  foo
  bar
  writer.println(new java.util.Date) 
})
// Which looks ugly
2 Likes

In what sense are we creating domain specific language (DSL) by using {} instead of ()?

In the sense that it looks like you are calling control flow structure called withPrintWriter. Many of the features of Scala can be combined to creating DSLs. Including multiple parameter lists, implicits, infix notation, optional parenthesis, etc.