Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Chris Hansen's <a href="http://polyglot-window.blogspot.com/2009/03/arm-blocks-in-scala-revisited.html" rel="noreferrer">blog entry 'ARM Blocks in Scala: Revisited' from 3/26/09</a> talks about about slide 21 of Martin Odersky's <a href="http://www.scala-lang.org/node/1261" rel="noreferrer">FOSDEM presentation</a>. This next block is taken straight from slide 21 (with permission): </p> <pre><code>def using[T &lt;: { def close() }] (resource: T) (block: T =&gt; Unit) { try { block(resource) } finally { if (resource != null) resource.close() } } </code></pre> <p>--end quote--</p> <p>Then we can call like this:</p> <pre><code>using(new BufferedReader(new FileReader("file"))) { r =&gt; var count = 0 while (r.readLine != null) count += 1 println(count) } </code></pre> <p>What are the drawbacks of this approach? That pattern would seem to address 95% of where I would need automatic resource management...</p> <p><strong>Edit:</strong> added code snippet</p> <hr> <p><strong>Edit2:</strong> extending the design pattern - taking inspiration from python <code>with</code> statement and addressing:</p> <ul> <li>statements to run before the block </li> <li>re-throwing exception depending on the managed resource</li> <li>handling two resources with one single using statement</li> <li>resource-specific handling by providing an implicit conversion and a <code>Managed</code> class</li> </ul> <p>This is with Scala 2.8.</p> <pre><code>trait Managed[T] { def onEnter(): T def onExit(t:Throwable = null): Unit def attempt(block: =&gt; Unit): Unit = { try { block } finally {} } } def using[T &lt;: Any](managed: Managed[T])(block: T =&gt; Unit) { val resource = managed.onEnter() var exception = false try { block(resource) } catch { case t:Throwable =&gt; exception = true; managed.onExit(t) } finally { if (!exception) managed.onExit() } } def using[T &lt;: Any, U &lt;: Any] (managed1: Managed[T], managed2: Managed[U]) (block: T =&gt; U =&gt; Unit) { using[T](managed1) { r =&gt; using[U](managed2) { s =&gt; block(r)(s) } } } class ManagedOS(out:OutputStream) extends Managed[OutputStream] { def onEnter(): OutputStream = out def onExit(t:Throwable = null): Unit = { attempt(out.close()) if (t != null) throw t } } class ManagedIS(in:InputStream) extends Managed[InputStream] { def onEnter(): InputStream = in def onExit(t:Throwable = null): Unit = { attempt(in.close()) if (t != null) throw t } } implicit def os2managed(out:OutputStream): Managed[OutputStream] = { return new ManagedOS(out) } implicit def is2managed(in:InputStream): Managed[InputStream] = { return new ManagedIS(in) } def main(args:Array[String]): Unit = { using(new FileInputStream("foo.txt"), new FileOutputStream("bar.txt")) { in =&gt; out =&gt; Iterator continually { in.read() } takeWhile( _ != -1) foreach { out.write(_) } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload