1

I'm learning scala and like the ability to come up with custom control structure, and as there's no using structure to close resources, I thought it'd be handy to write one. Then I found this snippet of code from the book, Beginning Scala, by David Pollak.

  using (Source.fromFile("file")) { source =>
    println(source.mkString)
  }

  def using[A <: { def close() }, B](closable: A)(body: A => B): B = 
  try 
    body(closable)
  finally 
    closable.close()

But I wonder whether would be possible to have something like:

  using (val source = Source.fromFile("file")) println(source.mkString)
Luis Mirabal
  • 2,606
  • 2
  • 16
  • 12
  • 1
    Related: [No. 1](http://stackoverflow.com/questions/2395984/scala-using-function) and [No. 2](http://stackoverflow.com/questions/2207425/what-automatic-resource-management-alternatives-exists-for-scala ) – 0__ Jun 01 '13 at 12:56
  • AFAIK no, because you are using "source: in the different scope, not the one you declared it)) But you can use for comprehensions to do this (monads), and CPS-like style that you posted above looks good enough to me. – vitalii Jun 01 '13 at 20:06

1 Answers1

2

As vitalli suggests, the short answer is no (sadly). Hopefully if I explain the method definition and invocation you found in Pollak's book then it will become clear why.

 def using[A <: { def close() }, B](closable: A)(body: A => B): B 

This using method definition has two parameter lists (see currying). Both lists have one parameter. The first parameter is a closable object (type A). The second is a function that goes from A to B.

When you invoke the method with this line:

using (Source.fromFile("file")) { source => println(source.mkString) }

The first argument is the return value of Source.fromFile("file") which is a closable BufferedSource. The second argument is an anonymous function that: takes one argument source, has one statement in its body println(source.mkString) and returns Unit.

The Scala compiler automatically detects the type of source from the method definition and the first argument you supplied (a BufferedSource). You could refactor out that anonymous function and declare the type explicitly if you wanted too:

using(Source.fromFile("file"))(eg)
def eg(source: BufferedSource): Unit = println(source.mkString)

But of course, the anonymous function is much more concise!

Community
  • 1
  • 1
Matt Roberts
  • 1,107
  • 10
  • 15