Quantcast

try/catch and fields in primary constructor

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

try/catch and fields in primary constructor

John Ky
Hi Scala users,

How do I declare fields inside a try/catch inside a primary constructor?

class Foo {
   val x = "x"

   try {
      val y = "y"
   } catch { case e: Exception =>
   }
}

object Main {
   def main(args: Array[String]): Unit = {
      println("Hello world")
      val foo = new Foo()
      println(foo.x)
      println(foo.y) // error
   }
}

Cheers,

-John
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

Tony Sloane
Use something like this:

val y = try { "y" } catch { ... }

Tony

On 18/01/2011, at 11:20 AM, John Ky wrote:

Hi Scala users,

How do I declare fields inside a try/catch inside a primary constructor?

class Foo {
   val x = "x"

   try {
      val y = "y"
   } catch { case e: Exception =>
   }
}

object Main {
   def main(args: Array[String]): Unit = {
      println("Hello world")
      val foo = new Foo()
      println(foo.x)
      println(foo.y) // error
   }
}

Cheers,

-John

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

John Ky
Hi Tony,

That works.  How about if I have lots of fields and want to share the same catch clause for all of them?

Cheers,

-John

On 18 January 2011 11:28, Tony Sloane <[hidden email]> wrote:
Use something like this:

val y = try { "y" } catch { ... }

Tony

On 18/01/2011, at 11:20 AM, John Ky wrote:

Hi Scala users,

How do I declare fields inside a try/catch inside a primary constructor?

class Foo {
   val x = "x"

   try {
      val y = "y"
   } catch { case e: Exception =>
   }
}

object Main {
   def main(args: Array[String]): Unit = {
      println("Hello world")
      val foo = new Foo()
      println(foo.x)
      println(foo.y) // error
   }
}

Cheers,

-John


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

Tony Sloane
You could attempt something like:

val (x,y) = try { ("x","y") } catch { ... }

but then it's getting much more obscure.

Tony

On 18/01/2011, at 11:35 AM, John Ky wrote:

Hi Tony,

That works.  How about if I have lots of fields and want to share the same catch clause for all of them?

Cheers,

-John

On 18 January 2011 11:28, Tony Sloane <[hidden email]> wrote:
Use something like this:

val y = try { "y" } catch { ... }

Tony

On 18/01/2011, at 11:20 AM, John Ky wrote:

Hi Scala users,

How do I declare fields inside a try/catch inside a primary constructor?

class Foo {
   val x = "x"

   try {
      val y = "y"
   } catch { case e: Exception =>
   }
}

object Main {
   def main(args: Array[String]): Unit = {
      println("Hello world")
      val foo = new Foo()
      println(foo.x)
      println(foo.y) // error
   }
}

Cheers,

-John



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

Paul Phillips-3
In reply to this post by John Ky
On Tue, Jan 18, 2011 at 11:35:58AM +1100, John Ky wrote:
> That works.  How about if I have lots of fields and want to share the
> same catch clause for all of them?

The present possibilities are fairly unfortunate, but I have some good
stuff in 2.9.  Write a fancy catch block once (or a fancy catch block
creating function) and reuse it.  Off the cuff:

object Test {
  def handler[T](value: T): PartialFunction[Throwable, T] = {
    case x: NullPointerException  => println("NPE") ; value
    case x: Exception => println(x) ; value
  }
 
  // drink in the beauty of the braces which do not exist
  val x = (
        try sys.error("oops")
      catch handler(5)
    finally println("fin")
  )
  val y = try null.toString catch handler("NPE")
 
  def main(args: Array[String]): Unit = { }
}

// output
% scala29 Test
java.lang.RuntimeException: oops
fin
NPE

--
Paul Phillips      | It's better to have gloved and tossed than never to
Protagonist        | have played baseball.
Empiricist         |
i pull his palp!   |----------* http://www.improving.org/paulp/ *----------
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

Ken Scambler
 val y = try null.toString catch handler("NPE")
 
Oh that is nice.  Repetition in catch blocks was always a big problem in Java.  Does it work with finally as well?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

Paul Phillips-3
On Tue, Jan 18, 2011 at 12:01:59PM +1100, Ken Scambler wrote:
> Oh that is nice.  Repetition in catch blocks was always a big problem
> in Java.  Does it work with finally as well?

It always did.

--
Paul Phillips      | Simplicity and elegance are unpopular because
Analgesic          | they require hard work and discipline to achieve
Empiricist         | and education to be appreciated.
all hip pupils!    |     -- Dijkstra
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

John Ky
In reply to this post by Paul Phillips-3
Hi Paul,

That sounds quite alright.

However, the use case I was struggling with is something like this:

class Foo {
  val a = Resource.open()
  val b = Resource.open()
  val c = Resource.open()
  val d = Resource.open()
}

If an exception is thrown anywhere in the constructor, I need to close any resources already opened, so something like this:

class Foo {
  val (a, b, c, d) = {
    val tempA = closer.closes(Resource.open())
    try {
      val tempB = closer.closes(Resource.open())
      try {
        val tempC = closer.closes(Resource.open())
        try {
          val tempD = closer.closes(Resource.open())
          (tempA, tempB, tempC, tempD)
        } catch { case e: Exception =>
          tempC.close()
          throw e
        }
      } catch { case e: Exception =>
        tempB.close()
        throw e
      }
    } catch { case e: Exception =>
      tempA.close()
      throw e
    }
  }
}

Or if I write a Closer class, which represents a list of objects to close, I can reduce it to this:

class Foo {
  val closer = new Closer()
  val (a, b, c, d) = try {
    val tempA = closer.closes(Resource.open())
    val tempB = closer.closes(Resource.open())
    val tempC = closer.closes(Resource.open())
    val tempD = closer.closes(Resource.open())
    (tempA, tempB, tempC, tempD)
  } catch { case e: Exception =>
    closer.closeAll()
    throw e
  }
}

Can I do any better?

Cheers,

-John

On 18 January 2011 11:55, Paul Phillips <[hidden email]> wrote:
On Tue, Jan 18, 2011 at 11:35:58AM +1100, John Ky wrote:
> That works.  How about if I have lots of fields and want to share the
> same catch clause for all of them?

The present possibilities are fairly unfortunate, but I have some good
stuff in 2.9.  Write a fancy catch block once (or a fancy catch block
creating function) and reuse it.  Off the cuff:

object Test {
 def handler[T](value: T): PartialFunction[Throwable, T] = {
   case x: NullPointerException  => println("NPE") ; value
   case x: Exception => println(x) ; value
 }

 // drink in the beauty of the braces which do not exist
 val x = (
       try sys.error("oops")
     catch handler(5)
   finally println("fin")
 )
 val y = try null.toString catch handler("NPE")

 def main(args: Array[String]): Unit = { }
}

// output
% scala29 Test
java.lang.RuntimeException: oops
fin
NPE

--
Paul Phillips      | It's better to have gloved and tossed than never to
Protagonist        | have played baseball.
Empiricist         |
i pull his palp!   |----------* http://www.improving.org/paulp/ *----------

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

Paul Phillips-3
On Tue, Jan 18, 2011 at 12:09:38PM +1100, John Ky wrote:
> That sounds quite alright.
>
> However, the use case I was struggling with is something like this:

Yes, I am familiar.

https://lampsvn.epfl.ch/trac/scala/ticket/3851
"Scope of variables declared in try block should extend to catch and finally"

I supported doing something (if not necessarily what was proposed) but
it was wontfixed.  So I'm not aware of anything beyond what you see on
the table.

--
Paul Phillips      | The most dangerous man to any government is the man who
In Theory          | is able to think things out [...] Almost inevitably he
Empiricist         | comes to the conclusion that the government he lives under
ha! spill, pupil   | is dishonest, insane, intolerable.   -- H. L. Mencken
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

Josh Suereth
In reply to this post by John Ky
I wrote a library (scala-arm) to help with this.  You may be particularly interested in the delimited continuations API.

I think trying to access resources in the catch block may perhaps be 'the wrong thing' because you need to null check everything to ensure there was no error before accessing this resource.  Using the ARM library, you can be assured that resources are closed in the inverse order they were opened, and that they are closed.

The basic usage works similar to your above closer idea, except you defer the opening of the resource block to for expressions.

val a = managed(Resources.open())
val b = managed(Resources.open())


//Later

for { a_ <- a
      b_ <- b } yield doSomethingAndReturn(a_,b_)

// or

for (a_ <- a; b_ <- b) { doSomething(a_,b_) }


Hope that helps!
- Josh



On Mon, Jan 17, 2011 at 8:09 PM, John Ky <[hidden email]> wrote:
Hi Paul,

That sounds quite alright.

However, the use case I was struggling with is something like this:

class Foo {
  val a = Resource.open()
  val b = Resource.open()
  val c = Resource.open()
  val d = Resource.open()
}

If an exception is thrown anywhere in the constructor, I need to close any resources already opened, so something like this:

class Foo {
  val (a, b, c, d) = {
    val tempA = closer.closes(Resource.open())
    try {
      val tempB = closer.closes(Resource.open())
      try {
        val tempC = closer.closes(Resource.open())
        try {
          val tempD = closer.closes(Resource.open())
          (tempA, tempB, tempC, tempD)
        } catch { case e: Exception =>
          tempC.close()
          throw e
        }
      } catch { case e: Exception =>
        tempB.close()
        throw e
      }
    } catch { case e: Exception =>
      tempA.close()
      throw e
    }
  }
}

Or if I write a Closer class, which represents a list of objects to close, I can reduce it to this:

class Foo {
  val closer = new Closer()
  val (a, b, c, d) = try {
    val tempA = closer.closes(Resource.open())
    val tempB = closer.closes(Resource.open())
    val tempC = closer.closes(Resource.open())
    val tempD = closer.closes(Resource.open())
    (tempA, tempB, tempC, tempD)
  } catch { case e: Exception =>
    closer.closeAll()
    throw e
  }
}

Can I do any better?

Cheers,

-John


On 18 January 2011 11:55, Paul Phillips <[hidden email]> wrote:
On Tue, Jan 18, 2011 at 11:35:58AM +1100, John Ky wrote:
> That works.  How about if I have lots of fields and want to share the
> same catch clause for all of them?

The present possibilities are fairly unfortunate, but I have some good
stuff in 2.9.  Write a fancy catch block once (or a fancy catch block
creating function) and reuse it.  Off the cuff:

object Test {
 def handler[T](value: T): PartialFunction[Throwable, T] = {
   case x: NullPointerException  => println("NPE") ; value
   case x: Exception => println(x) ; value
 }

 // drink in the beauty of the braces which do not exist
 val x = (
       try sys.error("oops")
     catch handler(5)
   finally println("fin")
 )
 val y = try null.toString catch handler("NPE")

 def main(args: Array[String]): Unit = { }
}

// output
% scala29 Test
java.lang.RuntimeException: oops
fin
NPE

--
Paul Phillips      | It's better to have gloved and tossed than never to
Protagonist        | have played baseball.
Empiricist         |
i pull his palp!   |----------* http://www.improving.org/paulp/ *----------


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

Jim Balter-2
In reply to this post by John Ky
Unfortunately, your code creates a couple of useless private tuple fields to hold the temporary.

But ... this doesn't seem like a very good approach to your use case. You might consider having a subclass of Resource that represents a failure to allocate a resource, including info about why -- it might even just be a wrapper for an Exception resulting from attempting to open the resource. Then you can just check to see if any of a,b,c,d contains such a failure. One possibility is Resource.needAll(rs: Resource*) that checks to see if any of its arguments represents a failure and if so closes the others and then throws an Exception (the thrown Exception should do the appropriate method overrides to combine the info of the failing cases); then you could simply write

class Foo {
  val a = Resource.open()
  val b = Resource.open()
  val c = Resource.open()
  val d = Resource.open()
  Resource.needAll(a, b, c, d)
}

There are numerous other straightforward possibilities once you abandon the control mess created by throwing Exceptions and return failure instances instead.

-- Jim

On Mon, Jan 17, 2011 at 5:09 PM, John Ky <[hidden email]> wrote:
Hi Paul,

That sounds quite alright.

However, the use case I was struggling with is something like this:

class Foo {
  val a = Resource.open()
  val b = Resource.open()
  val c = Resource.open()
  val d = Resource.open()
}

If an exception is thrown anywhere in the constructor, I need to close any resources already opened, so something like this:

class Foo {
  val (a, b, c, d) = {
    val tempA = closer.closes(Resource.open())
    try {
      val tempB = closer.closes(Resource.open())
      try {
        val tempC = closer.closes(Resource.open())
        try {
          val tempD = closer.closes(Resource.open())
          (tempA, tempB, tempC, tempD)
        } catch { case e: Exception =>
          tempC.close()
          throw e
        }
      } catch { case e: Exception =>
        tempB.close()
        throw e
      }
    } catch { case e: Exception =>
      tempA.close()
      throw e
    }
  }
}

Or if I write a Closer class, which represents a list of objects to close, I can reduce it to this:

class Foo {
  val closer = new Closer()
  val (a, b, c, d) = try {
    val tempA = closer.closes(Resource.open())
    val tempB = closer.closes(Resource.open())
    val tempC = closer.closes(Resource.open())
    val tempD = closer.closes(Resource.open())
    (tempA, tempB, tempC, tempD)
  } catch { case e: Exception =>
    closer.closeAll()
    throw e
  }
}

Can I do any better?

Cheers,

-John


On 18 January 2011 11:55, Paul Phillips <[hidden email]> wrote:
On Tue, Jan 18, 2011 at 11:35:58AM +1100, John Ky wrote:
> That works.  How about if I have lots of fields and want to share the
> same catch clause for all of them?

The present possibilities are fairly unfortunate, but I have some good
stuff in 2.9.  Write a fancy catch block once (or a fancy catch block
creating function) and reuse it.  Off the cuff:

object Test {
 def handler[T](value: T): PartialFunction[Throwable, T] = {
   case x: NullPointerException  => println("NPE") ; value
   case x: Exception => println(x) ; value
 }

 // drink in the beauty of the braces which do not exist
 val x = (
       try sys.error("oops")
     catch handler(5)
   finally println("fin")
 )
 val y = try null.toString catch handler("NPE")

 def main(args: Array[String]): Unit = { }
}

// output
% scala29 Test
java.lang.RuntimeException: oops
fin
NPE

--
Paul Phillips      | It's better to have gloved and tossed than never to
Protagonist        | have played baseball.
Empiricist         |
i pull his palp!   |----------* http://www.improving.org/paulp/ *----------


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

Derek Williams
On Mon, Jan 17, 2011 at 7:32 PM, Jim Balter <[hidden email]> wrote:
> There are numerous other straightforward possibilities once you abandon the
> control mess created by throwing Exceptions and return failure instances
> instead.

Scalaz is great for that kind of thing. this is probably almost
compilable (lots of examples floating around out there):

def open(): ValidationNel[Throwable, Result] = try {
  Resource.open().successNel
} catch {
  e => e.failNel
}

(open() |@| open() |@| open())(new Foo(_,_,_))

will return either a Success(Foo) or a
Failure(NonEmptyList(exception1, exception2,...))


--
Derek
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

John Ky
In reply to this post by Jim Balter-2
Hi Jim,

That's an interesting concept, however, doesn't it mean that if a fails then b, c, and d will still be created only to be discarded?

Also Resource.needAll is called from the primary constructor.  However the primary constructor can't be used to return values.  Doesn't it mean Resource.needAll must communicate errors by throwing an exception and as a result is contrary to the practise of returning error values?

i.e. I can't then compose Foo into Goo:

class Goo {
  val a = new Foo()
  val b = new Foo()
  val c = new Foo()
  val d = new Foo()
  Foo.needAll(a, b, c, d)
}

because Foo doesn't follow the suggested coding style.

Cheers,

-John

On 18 January 2011 13:32, Jim Balter <[hidden email]> wrote:
Unfortunately, your code creates a couple of useless private tuple fields to hold the temporary.

But ... this doesn't seem like a very good approach to your use case. You might consider having a subclass of Resource that represents a failure to allocate a resource, including info about why -- it might even just be a wrapper for an Exception resulting from attempting to open the resource. Then you can just check to see if any of a,b,c,d contains such a failure. One possibility is Resource.needAll(rs: Resource*) that checks to see if any of its arguments represents a failure and if so closes the others and then throws an Exception (the thrown Exception should do the appropriate method overrides to combine the info of the failing cases); then you could simply write

class Foo {
  val a = Resource.open()
  val b = Resource.open()
  val c = Resource.open()
  val d = Resource.open()
  Resource.needAll(a, b, c, d)
}

There are numerous other straightforward possibilities once you abandon the control mess created by throwing Exceptions and return failure instances instead.

-- Jim

On Mon, Jan 17, 2011 at 5:09 PM, John Ky <[hidden email]> wrote:
Hi Paul,

That sounds quite alright.

However, the use case I was struggling with is something like this:

class Foo {
  val a = Resource.open()
  val b = Resource.open()
  val c = Resource.open()
  val d = Resource.open()
}

If an exception is thrown anywhere in the constructor, I need to close any resources already opened, so something like this:

class Foo {
  val (a, b, c, d) = {
    val tempA = closer.closes(Resource.open())
    try {
      val tempB = closer.closes(Resource.open())
      try {
        val tempC = closer.closes(Resource.open())
        try {
          val tempD = closer.closes(Resource.open())
          (tempA, tempB, tempC, tempD)
        } catch { case e: Exception =>
          tempC.close()
          throw e
        }
      } catch { case e: Exception =>
        tempB.close()
        throw e
      }
    } catch { case e: Exception =>
      tempA.close()
      throw e
    }
  }
}

Or if I write a Closer class, which represents a list of objects to close, I can reduce it to this:

class Foo {
  val closer = new Closer()
  val (a, b, c, d) = try {
    val tempA = closer.closes(Resource.open())
    val tempB = closer.closes(Resource.open())
    val tempC = closer.closes(Resource.open())
    val tempD = closer.closes(Resource.open())
    (tempA, tempB, tempC, tempD)
  } catch { case e: Exception =>
    closer.closeAll()
    throw e
  }
}

Can I do any better?

Cheers,

-John


On 18 January 2011 11:55, Paul Phillips <[hidden email]> wrote:
On Tue, Jan 18, 2011 at 11:35:58AM +1100, John Ky wrote:
> That works.  How about if I have lots of fields and want to share the
> same catch clause for all of them?

The present possibilities are fairly unfortunate, but I have some good
stuff in 2.9.  Write a fancy catch block once (or a fancy catch block
creating function) and reuse it.  Off the cuff:

object Test {
 def handler[T](value: T): PartialFunction[Throwable, T] = {
   case x: NullPointerException  => println("NPE") ; value
   case x: Exception => println(x) ; value
 }

 // drink in the beauty of the braces which do not exist
 val x = (
       try sys.error("oops")
     catch handler(5)
   finally println("fin")
 )
 val y = try null.toString catch handler("NPE")

 def main(args: Array[String]): Unit = { }
}

// output
% scala29 Test
java.lang.RuntimeException: oops
fin
NPE

--
Paul Phillips      | It's better to have gloved and tossed than never to
Protagonist        | have played baseball.
Empiricist         |
i pull his palp!   |----------* http://www.improving.org/paulp/ *----------



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

Jim Balter-2
On Mon, Jan 17, 2011 at 7:37 PM, John Ky <[hidden email]> wrote:
Hi Jim,

That's an interesting concept, however, doesn't it mean that if a fails then b, c, and d will still be created only to be discarded?

Yes, but is this a valid objection or is it premature optimization? In your version, a, a and b, or a and b and c will be created only to be discarded if the later allocations fail. And if an earlier allocation fails because of a lack of resources or other persistent error, then the later ones will too and so they won't be created only to be discarded. If Resource.open takes parameters and a, b, c, and d are independent, then you might well want to know their failure conditions independently -- e.g., if I try to concatenate four files, I would consider it a feature to report *all* of those that can't be opened and why, rather than reporting on only the first failure. And if a, b, c, and d aren't independent, then presumably the later allocations will fail because the earlier ones did.

But if you really really need to optimize the failure cases, Resource.open could take a Resource* that is checked before allocation, returning failure if any of them were failures:

class Foo {
  // each is only allocated if all of the preceding succeeded
  val a = new Resource.open()
  val b = new Resource.open(a,b)
  val c = new Resource.open(a,b,c)
  val d = new Resource.open(a,b,c,d)
  if( d.failed ) Resource.closeAndThrow(a,b,c,d) // among other possibilities
}


Also Resource.needAll is called from the primary constructor.  However the primary constructor can't be used to return values.  Doesn't it mean Resource.needAll must communicate errors by throwing an exception and as a result is contrary to the practise of returning error values?

i.e. I can't then compose Foo into Goo:

class Goo {
  val a = new Foo()
  val b = new Foo()
  val c = new Foo()
  val d = new Foo()
  Foo.needAll(a, b, c, d)
}

because Foo doesn't follow the suggested coding style.


If you want a return value, use a factory method, as you did with Resource.open. A private constructor would throw the exception, which would be packaged into a failure instance by the factory method. If you call Foo's factory method "apply", you can simply omit the "new"s above.

-- Jim

 

On 18 January 2011 13:32, Jim Balter <[hidden email]> wrote:
Unfortunately, your code creates a couple of useless private tuple fields to hold the temporary.

But ... this doesn't seem like a very good approach to your use case. You might consider having a subclass of Resource that represents a failure to allocate a resource, including info about why -- it might even just be a wrapper for an Exception resulting from attempting to open the resource. Then you can just check to see if any of a,b,c,d contains such a failure. One possibility is Resource.needAll(rs: Resource*) that checks to see if any of its arguments represents a failure and if so closes the others and then throws an Exception (the thrown Exception should do the appropriate method overrides to combine the info of the failing cases); then you could simply write

class Foo {
  val a = Resource.open()
  val b = Resource.open()
  val c = Resource.open()
  val d = Resource.open()
  Resource.needAll(a, b, c, d)
}

There are numerous other straightforward possibilities once you abandon the control mess created by throwing Exceptions and return failure instances instead.

-- Jim

On Mon, Jan 17, 2011 at 5:09 PM, John Ky <[hidden email]> wrote:
Hi Paul,

That sounds quite alright.

However, the use case I was struggling with is something like this:

class Foo {
  val a = Resource.open()
  val b = Resource.open()
  val c = Resource.open()
  val d = Resource.open()
}

If an exception is thrown anywhere in the constructor, I need to close any resources already opened, so something like this:

class Foo {
  val (a, b, c, d) = {
    val tempA = closer.closes(Resource.open())
    try {
      val tempB = closer.closes(Resource.open())
      try {
        val tempC = closer.closes(Resource.open())
        try {
          val tempD = closer.closes(Resource.open())
          (tempA, tempB, tempC, tempD)
        } catch { case e: Exception =>
          tempC.close()
          throw e
        }
      } catch { case e: Exception =>
        tempB.close()
        throw e
      }
    } catch { case e: Exception =>
      tempA.close()
      throw e
    }
  }
}

Or if I write a Closer class, which represents a list of objects to close, I can reduce it to this:

class Foo {
  val closer = new Closer()
  val (a, b, c, d) = try {
    val tempA = closer.closes(Resource.open())
    val tempB = closer.closes(Resource.open())
    val tempC = closer.closes(Resource.open())
    val tempD = closer.closes(Resource.open())
    (tempA, tempB, tempC, tempD)
  } catch { case e: Exception =>
    closer.closeAll()
    throw e
  }
}

Can I do any better?

Cheers,

-John


On 18 January 2011 11:55, Paul Phillips <[hidden email]> wrote:
On Tue, Jan 18, 2011 at 11:35:58AM +1100, John Ky wrote:
> That works.  How about if I have lots of fields and want to share the
> same catch clause for all of them?

The present possibilities are fairly unfortunate, but I have some good
stuff in 2.9.  Write a fancy catch block once (or a fancy catch block
creating function) and reuse it.  Off the cuff:

object Test {
 def handler[T](value: T): PartialFunction[Throwable, T] = {
   case x: NullPointerException  => println("NPE") ; value
   case x: Exception => println(x) ; value
 }

 // drink in the beauty of the braces which do not exist
 val x = (
       try sys.error("oops")
     catch handler(5)
   finally println("fin")
 )
 val y = try null.toString catch handler("NPE")

 def main(args: Array[String]): Unit = { }
}

// output
% scala29 Test
java.lang.RuntimeException: oops
fin
NPE

--
Paul Phillips      | It's better to have gloved and tossed than never to
Protagonist        | have played baseball.
Empiricist         |
i pull his palp!   |----------* http://www.improving.org/paulp/ *----------




Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

John Ky
In reply to this post by Jim Balter-2
Hi Jim,

Oh - there it is:

$ javap -classpath . -private Foo
Compiled from "Hello.scala"
public class Foo extends java.lang.Object implements scala.ScalaObject{
    private final scala.Tuple2 x$1;
    private final java.lang.String x;
    private final java.lang.String y;
    public java.lang.String x();
    public java.lang.String y();
    private final scala.Tuple2 liftedTree1$1();
    public Foo();
}

I was a little unsure about it because I didn't see it here:

$ scalap -classpath . -private Foo
class Foo extends java.lang.Object with scala.ScalaObject {
  def this() = { /* compiled code */ }
  val x : java.lang.String = { /* compiled code */ }
  val y : java.lang.String = { /* compiled code */ }
}

Factory methods it is then.

Cheers,

-John


On 18 January 2011 13:32, Jim Balter <[hidden email]> wrote:
Unfortunately, your code creates a couple of useless private tuple fields to hold the temporary.

But ... this doesn't seem like a very good approach to your use case. You might consider having a subclass of Resource that represents a failure to allocate a resource, including info about why -- it might even just be a wrapper for an Exception resulting from attempting to open the resource. Then you can just check to see if any of a,b,c,d contains such a failure. One possibility is Resource.needAll(rs: Resource*) that checks to see if any of its arguments represents a failure and if so closes the others and then throws an Exception (the thrown Exception should do the appropriate method overrides to combine the info of the failing cases); then you could simply write

class Foo {
  val a = Resource.open()
  val b = Resource.open()
  val c = Resource.open()
  val d = Resource.open()
  Resource.needAll(a, b, c, d)
}

There are numerous other straightforward possibilities once you abandon the control mess created by throwing Exceptions and return failure instances instead.

-- Jim

On Mon, Jan 17, 2011 at 5:09 PM, John Ky <[hidden email]> wrote:
Hi Paul,

That sounds quite alright.

However, the use case I was struggling with is something like this:

class Foo {
  val a = Resource.open()
  val b = Resource.open()
  val c = Resource.open()
  val d = Resource.open()
}

If an exception is thrown anywhere in the constructor, I need to close any resources already opened, so something like this:

class Foo {
  val (a, b, c, d) = {
    val tempA = closer.closes(Resource.open())
    try {
      val tempB = closer.closes(Resource.open())
      try {
        val tempC = closer.closes(Resource.open())
        try {
          val tempD = closer.closes(Resource.open())
          (tempA, tempB, tempC, tempD)
        } catch { case e: Exception =>
          tempC.close()
          throw e
        }
      } catch { case e: Exception =>
        tempB.close()
        throw e
      }
    } catch { case e: Exception =>
      tempA.close()
      throw e
    }
  }
}

Or if I write a Closer class, which represents a list of objects to close, I can reduce it to this:

class Foo {
  val closer = new Closer()
  val (a, b, c, d) = try {
    val tempA = closer.closes(Resource.open())
    val tempB = closer.closes(Resource.open())
    val tempC = closer.closes(Resource.open())
    val tempD = closer.closes(Resource.open())
    (tempA, tempB, tempC, tempD)
  } catch { case e: Exception =>
    closer.closeAll()
    throw e
  }
}

Can I do any better?

Cheers,

-John


On 18 January 2011 11:55, Paul Phillips <[hidden email]> wrote:
On Tue, Jan 18, 2011 at 11:35:58AM +1100, John Ky wrote:
> That works.  How about if I have lots of fields and want to share the
> same catch clause for all of them?

The present possibilities are fairly unfortunate, but I have some good
stuff in 2.9.  Write a fancy catch block once (or a fancy catch block
creating function) and reuse it.  Off the cuff:

object Test {
 def handler[T](value: T): PartialFunction[Throwable, T] = {
   case x: NullPointerException  => println("NPE") ; value
   case x: Exception => println(x) ; value
 }

 // drink in the beauty of the braces which do not exist
 val x = (
       try sys.error("oops")
     catch handler(5)
   finally println("fin")
 )
 val y = try null.toString catch handler("NPE")

 def main(args: Array[String]): Unit = { }
}

// output
% scala29 Test
java.lang.RuntimeException: oops
fin
NPE

--
Paul Phillips      | It's better to have gloved and tossed than never to
Protagonist        | have played baseball.
Empiricist         |
i pull his palp!   |----------* http://www.improving.org/paulp/ *----------



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

Jim Balter-2
In reply to this post by Derek Williams

On Mon, Jan 17, 2011 at 7:01 PM, Derek Williams <[hidden email]> wrote:
On Mon, Jan 17, 2011 at 7:32 PM, Jim Balter <[hidden email]> wrote:
> There are numerous other straightforward possibilities once you abandon the
> control mess created by throwing Exceptions and return failure instances
> instead.

Scalaz is great for that kind of thing. this is probably almost
compilable (lots of examples floating around out there):

def open(): ValidationNel[Throwable, Result] = try {
 Resource.open().successNel
} catch {
 e => e.failNel
}

(open() |@| open() |@| open())(new Foo(_,_,_))

will return either a Success(Foo) or a
Failure(NonEmptyList(exception1, exception2,...))


--
Derek

That's a nice approach. Foo could have a private constructor that takes Resources that have already been opened. object Foo's apply method would do the one-liner. It's all quite composable. Too bad Scalaz is so short on documentation.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

John Ky
In reply to this post by Derek Williams
Hi Derek,

Took me a while to digest it, but some nice concepts there so thank you.

Cheers,

-John

On 18 January 2011 14:01, Derek Williams <[hidden email]> wrote:
On Mon, Jan 17, 2011 at 7:32 PM, Jim Balter <[hidden email]> wrote:
> There are numerous other straightforward possibilities once you abandon the
> control mess created by throwing Exceptions and return failure instances
> instead.

Scalaz is great for that kind of thing. this is probably almost
compilable (lots of examples floating around out there):

def open(): ValidationNel[Throwable, Result] = try {
 Resource.open().successNel
} catch {
 e => e.failNel
}

(open() |@| open() |@| open())(new Foo(_,_,_))

will return either a Success(Foo) or a
Failure(NonEmptyList(exception1, exception2,...))


--
Derek

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: try/catch and fields in primary constructor

John Ky
In reply to this post by John Ky
Hi all,

It just occurred to me I could have defined my Disposer class to do all the necessary catching and rollback thus:

class Disposer extends Disposable {
  private var list: List[Disposable] = Nil

  def disposes[D <: Disposable](disposable: => D): D = {
    val disposableInstance = try {
      disposable
    } catch { case e =>
      this.dispose()
      throw e
    }

    list = disposableInstance :: list
    
    return disposableInstance
  }
  
  override def dispose(): Unit = {
    list.foreach { disposable =>
      try {
        disposable.dispose()
      } catch { case e =>
      }
    }
  }
}

This means allows me to define my Foo class like so:

class Foo {
  val disposer = new Disposer
  val a = disposer.disposes(Resource.open())
  val b = disposer.disposes(Resource.open())
  val c = disposer.disposes(Resource.open())
  val d = disposer.disposes(Resource.open())
}

Because the disposes method now takes a function returning a disposable value rather than the disposable value itself, the Resource.open() is called from within the disposes method where it can be caught and a full roll back of allocations can be triggered transparently.

It does mean my Foo class has an extra disposer field, but as it turns out, that isn't so bad because the field lets me define my Foo.dispose method in one line:

class Foo extends Disposable {
  val disposer = new Disposer
  val a = disposer.disposes(Resource.open())
  val b = disposer.disposes(Resource.open())
  val c = disposer.disposes(Resource.open())
  val d = disposer.disposes(Resource.open())

  def dispose(): Unit = disposer.dispose()
}

So it was convenient to have it around anyway.

Cheers,

-John

On 18 January 2011 11:20, John Ky <[hidden email]> wrote:
Hi Scala users,

How do I declare fields inside a try/catch inside a primary constructor?

class Foo {
   val x = "x"

   try {
      val y = "y"
   } catch { case e: Exception =>
   }
}

object Main {
   def main(args: Array[String]): Unit = {
      println("Hello world")
      val foo = new Foo()
      println(foo.x)
      println(foo.y) // error
   }
}

Cheers,

-John

Loading...