I have the following snippet of code:
val oldStep = step
try {
someDangerousActionPotentiallyModifyingStep()
} finally {
step = oldStep
}
Is it possible to write a generic helper method to abstract away the pattern? Then I could use the helper method like this:
remember(step) {
someDangerousActionPotentiallyModifyingStep()
}
Of course the following approach does not work, because Scala does not support pass by reference:
def remember[T](x: T)(action: => Unit) {
val previousValue = x
try {
action
} finally {
x = previousValue
}
}
I solved the problem by changing the step data member into an implicit parameter. That way, I never have to restore the old value of step, because its value never changes inside the same scope :)
The problem is that a var does not give you enough control to do what you want to do.
As a direct answer to your question: you need an object with an update method instead of a field. Something like this:
class Box[T](var value:T) {
def apply = value
def update(newValue:T) { value = newValue }
override def toString = value.toString
}
Then you can solve your problem like this:
def remember[T](box:Box[T])(action: =>Unit) {
val prev = box.apply
try {
action
} catch {
case _ => box() = prev
}
}
val step = new Box(0)
// working update
remember(step) { step() = 4 }
// step is now 4
// aborted update
remember(step) { step() = 5; throw new Exception }
// step is still 4
But note that this is really not very idiomatic scala. You should try to make your someDangerousActionPotentiallyModifyingStep a side-effect-free function that returns the new step.
Basically like this:
try {
step = someDangerousFunctionOfStep(step)
} catch {
case _ => // we don't have to do anything because step is still the same
}
If that is not possible for some reason, you might want to investigate Akka agents, which are conceptually similar to the Box above, except with the difference that they are thread-safe and can be used in a transactional way.
Here is how you would use akka agents to solve the problem:
First you need an actor system:
implicit val actorSystem = akka.actor.ActorSystem("test")
Then you can define an agent containing the step value
val step = akka.agent.Agent(0)
Now you can update it in a transaction:
import scala.concurrent.stm._
atomic { txn => step() = 4 }
// step.get will now return 4
atomic { txn => step() = 5; throw new Exception }
// step.get will still return 5. You will have to catch the exception if you don't want
// it to propagate outward
The real power of akka agents comes when you have multiple agents and update them atomically. See the akka agents docs for the canonical "account transfer" transaction example.
It's pretty ugly (and an affront to immutability), but you could try something like this:
def remember[T](newT:T, get: => T, set:(T) => Unit)(action: => Unit) = {
var old = get
set(newT)
try{
action
}
finally{
set(old)
}
}
And then use it like this:
var x = "hello"
remember[String]("world", x, x = _){
//do something dangerous here
}
I think you're looking for Loan pattern.
http://blog.knoldus.com/2012/11/16/scalaknol-understanding-loan-pattern/
Related
Consider a Model for Master/Slave election for a cluster.
Member{ id: Long, isMaster: Boolean }
I have a Dao/Repo with following methods:
MemberDao.findById(id:Long):Future[Option[Member]]
MemberDao.update(id:Long, member: Member):Future[Unit]
MemberDao.all() : Future[List[Member]]
Within the MemberService, I'm trying to write a function to set isMaster to false for all existing members, and I'm ending up with this crazily bloated code:
class MemberService ... {
def demoteAllMembers() : Future[Boolean] = {
val futures = memberDao.all.map{ memberFuture =>
memberFuture.map{ member =>
memberDao.findById(member.id).map { existingMemberFuture =>
existingMemberFuture.map { existingMember =>
memberDao.update(existingMember.id, existingMember.copy(isMaster = false)
}
}
}
val results = Await.result(futures, 10 seconds)
// return something here
}
}
}
My Questions are:
1. How should the return statement be written to handle success / errors? e.g. On success, return Future(true) and on failure, return Future(false)
2. Is this way of repetitively mapping future the correct way of doing async programming in scala? I understand this could be written differently in Actor paradigm and probably much better, but in case of OOP, is this the best Scala can do?
Thanks.
Why are you doing MemberDao.findById when you are already holding a member in hand??? (You are also treating the return as a Member, while it should really be an Option[Member]).
Also, update does not need to take an id as a separate parameter (there is one available inside member).
You don't need to Await your result, because your function is returning a Future, and you don't need to return a Boolean: just throw an exception to signal failure.
Consider something like this:
def demoteAllMembers: Future[Unit] = memberDao.all.flatMap {
Future.sequence(_.foreach {
memberDao.update(_.copy(isMaster = false))
})
}.map ( _ => () )
Not all that bloated, is it? :)
Suppose this API is given and we cannot change it:
object ProviderAPI {
trait Receiver[T] {
def receive(entry: T)
def close()
}
def run(r: Receiver[Int]) {
new Thread() {
override def run() {
(0 to 9).foreach { i =>
r.receive(i)
Thread.sleep(100)
}
r.close()
}
}.start()
}
}
In this example, ProviderAPI.run takes a Receiver, calls receive(i) 10 times and then closes. Typically, ProviderAPI.run would call receive(i) based on a collection which could be infinite.
This API is intended to be used in imperative style, like an external iterator. If our application needs to filter, map and print this input, we need to implement a Receiver which mixes all these operations:
object Main extends App {
class MyReceiver extends ProviderAPI.Receiver[Int] {
def receive(entry: Int) {
if (entry % 2 == 0) {
println("Entry#" + entry)
}
}
def close() {}
}
ProviderAPI.run(new MyReceiver())
}
Now, the question is how to use the ProviderAPI in functional style, internal iterator (without changing the implementation of ProviderAPI, which is given to us). Note that ProviderAPI could also call receive(i) infinite times, so it is not an option to collect everything in a list (also, we should handle each result one by one, instead of collecting all the input first, and processing it afterwards).
I am asking how to implement such a ReceiverToIterator, so that we can use the ProviderAPI in functional style:
object Main extends App {
val iterator = new ReceiverToIterator[Int] // how to implement this?
ProviderAPI.run(iterator)
iterator
.view
.filter(_ % 2 == 0)
.map("Entry#" + _)
.foreach(println)
}
Update
Here are four solutions:
IteratorWithSemaphorSolution: The workaround solution I proposed first attached to the question
QueueIteratorSolution: Using the BlockingQueue[Option[T]] based on the suggestion of nadavwr.
It allows the producer to continue producing up to queueCapacity before being blocked by the consumer.
PublishSubjectSolution: Very simple solution, using PublishSubject from Netflix RxJava-Scala API.
SameThreadReceiverToTraversable: Very simple solution, by relaxing the constraints of the question
Updated: BlockingQueue of 1 entry
What you've implemented here is essentially Java's BlockingQueue, with a queue size of 1.
Main characteristic: uber-blocking. A slow consumer will kill your producer's performance.
Update: #gzm0 mentioned that BlockingQueue doesn't cover EOF. You'll have to use BlockingQueue[Option[T]] for that.
Update: Here's a code fragment. It can be made to fit with your Receiver.
Some of it inspired by Iterator.buffered. Note that peek is a misleading name, as it may block -- and so will hasNext.
// fairness enabled -- you probably want to preserve order...
// alternatively, disable fairness and increase buffer to be 'big enough'
private val queue = new java.util.concurrent.ArrayBlockingQueue[Option[T]](1, true)
// the following block provides you with a potentially blocking peek operation
// it should `queue.take` when the previous peeked head has been invalidated
// specifically, it will `queue.take` and block when the queue is empty
private var head: Option[T] = _
private var headDefined: Boolean = false
private def invalidateHead() { headDefined = false }
private def peek: Option[T] = {
if (!headDefined) {
head = queue.take()
headDefined = true
}
head
}
def iterator = new Iterator[T] {
// potentially blocking; only false upon taking `None`
def hasNext = peek.isDefined
// peeks and invalidates head; throws NoSuchElementException as appropriate
def next: T = {
val opt = peek; invalidateHead()
if (opt.isEmpty) throw new NoSuchElementException
else opt.get
}
}
Alternative: Iteratees
Iterator-based solutions will generally involve more blocking. Conceptually, you could use continuations on the thread doing the iteration to avoid blocking the thread, but continuations mess with Scala's for-comprehensions, so no joy down that road.
Alternatively, you could consider an iteratee-based solution. Iteratees are different than iterators in that the consumer isn't responsible for advancing the iteration -- the producer is. With iteratees, the consumer basically folds over the entries pushed by the producer over time. Folding each next entry as it becomes available can take place in a thread pool, since the thread is relinquished after each fold completes.
You won't get nice for-syntax for iteration, and the learning curve is a little challenging, but if you feel confident using a foldLeft you'll end up with a non-blocking solution that does look reasonable on the eye.
To read more about iteratees, I suggest taking a peek at PlayFramework 2.X's iteratee reference. The documentation describes their stand-alone iteratee library, which is 100% usable outside the context of Play. Scalaz 7 also has a comprehensive iteratee library.
IteratorWithSemaphorSolution
The first workaround solution that I proposed attached to the question.
I moved it here as an answer.
import java.util.concurrent.Semaphore
object Main extends App {
val iterator = new ReceiverToIterator[Int]
ProviderAPI.run(iterator)
iterator
.filter(_ % 2 == 0)
.map("Entry#" + _)
.foreach(println)
}
class ReceiverToIterator[T] extends ProviderAPI.Receiver[T] with Iterator[T] {
var lastEntry: T = _
var waitingToReceive = new Semaphore(1)
var waitingToBeConsumed = new Semaphore(1)
var eof = false
waitingToReceive.acquire()
def receive(entry: T) {
println("ReceiverToIterator.receive(" + entry + "). START.")
waitingToBeConsumed.acquire()
lastEntry = entry
waitingToReceive.release()
println("ReceiverToIterator.receive(" + entry + "). END.")
}
def close() {
println("ReceiverToIterator.close().")
eof = true
waitingToReceive.release()
}
def hasNext = {
println("ReceiverToIterator.hasNext().START.")
waitingToReceive.acquire()
waitingToReceive.release()
println("ReceiverToIterator.hasNext().END.")
!eof
}
def next = {
println("ReceiverToIterator.next().START.")
waitingToReceive.acquire()
if (eof) { throw new NoSuchElementException }
val entryToReturn = lastEntry
waitingToBeConsumed.release()
println("ReceiverToIterator.next().END.")
entryToReturn
}
}
QueueIteratorSolution
The second workaround solution that I proposed attached to the question. I moved it here as an answer.
Solution using the BlockingQueue[Option[T]] based on the suggestion of nadavwr.
It allows the producer to continue producing up to queueCapacity before being blocked by the consumer.
I implement a QueueToIterator that uses a ArrayBlockingQueue with a given capacity.
BlockingQueue has a take() method, but not a peek or hasNext, so I need an OptionNextToIterator as follows:
trait OptionNextToIterator[T] extends Iterator[T] {
def getOptionNext: Option[T] // abstract
def hasNext = { ... }
def next = { ... }
}
Note: I am using the synchronized block inside OptionNextToIterator, and I am not sure it is totally correct
Solution:
import java.util.concurrent.ArrayBlockingQueue
object Main extends App {
val receiverToIterator = new ReceiverToIterator[Int](queueCapacity = 3)
ProviderAPI.run(receiverToIterator)
Thread.sleep(3000) // test that ProviderAPI.run can produce 3 items ahead before being blocked by the consumer
receiverToIterator.filter(_ % 2 == 0).map("Entry#" + _).foreach(println)
}
class ReceiverToIterator[T](val queueCapacity: Int = 1) extends ProviderAPI.Receiver[T] with QueueToIterator[T] {
def receive(entry: T) { queuePut(entry) }
def close() { queueClose() }
}
trait QueueToIterator[T] extends OptionNextToIterator[T] {
val queueCapacity: Int
val queue = new ArrayBlockingQueue[Option[T]](queueCapacity)
var queueClosed = false
def queuePut(entry: T) {
if (queueClosed) { throw new IllegalStateException("The queue has already been closed."); }
queue.put(Some(entry))
}
def queueClose() {
queueClosed = true
queue.put(None)
}
def getOptionNext = queue.take
}
trait OptionNextToIterator[T] extends Iterator[T] {
def getOptionNext: Option[T]
var answerReady: Boolean = false
var eof: Boolean = false
var element: T = _
def hasNext = {
prepareNextAnswerIfNecessary()
!eof
}
def next = {
prepareNextAnswerIfNecessary()
if (eof) { throw new NoSuchElementException }
val retVal = element
answerReady = false
retVal
}
def prepareNextAnswerIfNecessary() {
if (answerReady) {
return
}
synchronized {
getOptionNext match {
case None => eof = true
case Some(e) => element = e
}
answerReady = true
}
}
}
PublishSubjectSolution
A very simple solution using PublishSubject from Netflix RxJava-Scala API:
// libraryDependencies += "com.netflix.rxjava" % "rxjava-scala" % "0.20.7"
import rx.lang.scala.subjects.PublishSubject
class MyReceiver[T] extends ProviderAPI.Receiver[T] {
val channel = PublishSubject[T]()
def receive(entry: T) { channel.onNext(entry) }
def close() { channel.onCompleted() }
}
object Main extends App {
val myReceiver = new MyReceiver[Int]()
ProviderAPI.run(myReceiver)
myReceiver.channel.filter(_ % 2 == 0).map("Entry#" + _).subscribe{n => println(n)}
}
ReceiverToTraversable
This stackoverflow question came when I wanted to list and process a svn repository using the svnkit.com API as follows:
SvnList svnList = new SvnOperationFactory().createList();
svnList.setReceiver(new ISvnObjectReceiver<SVNDirEntry>() {
public void receive(SvnTarget target, SVNDirEntry dirEntry) throws SVNException {
// do something with dirEntry
}
});
svnList.run();
the API used a callback function, and I wanted to use a functional style instead, as follows:
svnList.
.filter(e => "pom.xml".compareToIgnoreCase(e.getName()) == 0)
.map(_.getURL)
.map(getMavenArtifact)
.foreach(insertArtifact)
I thought of having a class ReceiverToIterator[T] extends ProviderAPI.Receiver[T] with Iterator[T],
but this required the svnkit api to run in another thread.
That's why I asked how to solve this problem with a ProviderAPI.run method that run in a new thread. But that was not very wise: if I had explained the real case, someone might have found a better solution before.
Solution
If we tackle the real problem (so, no need of using a thread for the svnkit),
a simpler solution is to implement a scala.collection.Traversable instead of a scala.collection.Iterator.
While Iterator requires a next and hasNext def, Traversable requires a foreach def,
which is very similar to the svnkit callback!
Note that by using view, we make the transformers lazy, so elements are passed one by one through all the chain to foreach(println).
this allows to process an infinite collection.
object ProviderAPI {
trait Receiver[T] {
def receive(entry: T)
def close()
}
// Later I found out that I don't need a thread
def run(r: Receiver[Int]) {
(0 to 9).foreach { i => r.receive(i); Thread.sleep(100) }
}
}
object Main extends App {
new ReceiverToTraversable[Int](r => ProviderAPI.run(r))
.view
.filter(_ % 2 == 0)
.map("Entry#" + _)
.foreach(println)
}
class ReceiverToTraversable[T](val runProducer: (ProviderAPI.Receiver[T] => Unit)) extends Traversable[T] {
override def foreach[U](f: (T) => U) = {
object MyReceiver extends ProviderAPI.Receiver[T] {
def receive(entry: T) = f(entry)
def close() = {}
}
runProducer(MyReceiver)
}
}
I am struggling with the type system. I get a "error: type mismatch" at the line
handler.addJob(job1)
It says found "MessageEvent" required "Event"
I think that I need to somehow change the addJob method to pass in any Job with a type that extends Event but I can't figure out how to do that.
Also the line
var jobs = List[Job[Event]]()
should probably take a job with a subtype of Event but again I don't know how to do that. Any help is appreciated.
-Eric
class EventHandler {
var jobs = List[Job[Event]]()
def receive(event: Event) {
jobs.foreach {
_.processEvent(event)
}
}
def addJob(job: Job[Event]) {
jobs = job :: jobs
}
}
class Job[T <: Event] {
var steps = List[(T => Unit)]()
def addStep(step: (T => Unit)) {
steps = step :: steps
}
def processEvent(event: T): Boolean = {
steps.foreach(_.apply(event))
return true
}
}
class AppTest {
def testApp {
val handler = new EventHandler()
val job1 = new Job[MessageEvent]
job1.addStep {
println(_)
}
handler.addJob(job1)
handler.receive(new MessageEvent(new Message()))
}
}
The problems you mention are easy to fix:
class EventHandler {
var jobs = List[Job[_]]()
def receive(event: Event) {
jobs.foreach {
_.processEvent(event)
}
}
def addJob(job: Job[_]) {
jobs = job :: jobs
}
}
But this shows another problem with the receive method: you need each job to process any Event. This can be fixed using Manifests to work around type erasure:
class Job[T <: Event : ClassManifest] {
val clazz: Class[T] = implicitly[ClassManifest[T]].asInstanceOf[Class[T]]
var steps = List[(T => Unit)]()
def addStep(step: (T => Unit)) {
steps = step :: steps
}
def processEvent1(event: Event): Boolean = {
try {
processEvent(clazz.cast(event))
}
catch {
case e: ClassCastException => false
}
}
def processEvent(event: T): Boolean = {
steps.foreach(_.apply(event))
return true
}
}
Changing addJobs:
def addJob[T <: Event](job: Job[T]) {
jobs = job :: jobs
}
But jobs won't work with that, since Job[MessageEvent] is not a Job[Event]. The only way to get that is to make Job co-variant, but, unfortunately, you can't make Job co-variant as it is.
Why don't you, instead, completely removes Job's parameterization and use Event internally? You can then use T <: Event (like above in addJob) with addStep and processEvent, if necessary.
Based on your example, it looks as though you'll be building the Job and EventHandler instances statically. In this case, you really don't need those classes at all!
Starting with Job. This performs two roles:
maintain a list of T => Unit functions
execute those functions
(it's also worth noting that :: prepends, so steps will be executed in the reverse of the order they were added)
Building and maintaining that list of functions at runtime (within a mutable list) can be completely avoided if you already know what they'll be when the thing compiles. This is most naturally done with an aggregate function:
val job = (m: MessageEvent) => {
log.debug(m)
println(m)
somethingElse(m)
}
Instead of holding a List[Job[Event]], this means that EventHandler now holds a List[(T => Unit)] (as Job previously did). So rinse and repeat...
I have a resource object stored in an option.
private var ochan: Option[Channel] = None
At some point during program execution, ochan is set to Some(channel). I'd like to close the channel (via invoking the method close) and set the option to None in one fatal swoop.
Currently I have:
def disconnect = ochan = { ochan.foreach{_.close}; None }
And previously I had:
def disconnect = ochan = ochan.flatMap{ o => o.close; None }
Is there a better way to do this?
I'd write it like this:
def disconnect = ochan = ochan match {
case Some(ch) => ch.close(); None
case None => None // do nothing
}
instead of using foreach or flatMap. In my opinion, this solution shows more clearly and explicitly what happens. The solution with foreach or flatMap requires an extra mental jump, you'd have to know what these methods do on an Option.
I don't know that it's better but it's shorter (once you've defined the implicit):
implicit def closer(o: Option[Channel]) = new {
def close(): Option[Channel] = { o.foreach(_.close); None }
}
def disconnect = ochan = ochan.close
There is no big difference between an immutable var and a mutable val. So why not encapsulate the behavior in a separate class, when you want to have mutability anyway?
class ChannelOption {
private var _channel :Option[Channel] = None
def channel = _channel
def channel_=(ch:Option[Channel]) { _channel.foreach(_.close); _channel = ch }
}
Usage:
private val ochan = new ChannelOption
ochan.channel = Some(getAChannel)
ochan.channel.foreach(useChannel)
ochan.channel = Some(getAnotherChannel) //this automatically closes the first channel
ochan.channel = None //this automatically closes the second channel
It's not thread safe! Remember to use #volatile (not here; using synchronization), and do something like this: (this is why I don't like imperative code)
private val lock = new Object
def disconnect() {//Function has side effects: remember parenthesis!
lock.synchronized { //Synchronizations is important; you don't want to close it multiple times
ochan.foreach {_.close()} //Again: side effects -> parens.
}
}
And if you don't use parallel programming, you are doing something wrong.
You could define ochan_= so that assigning a new value to ochan closes the old channel (similar to std::auto_ptr<> in C++) but I don't see how you can encapsulate that in a child class of Option[Channel] because the storage is in your class. The solution wouldn't change the code much at all, it would just make disconnect implicit by assigning ochan.
I guess this could work:
def disconnect {
ochan = {
ochan.get.close
None
}
}
or
def disconnect {
ochan.get.close
ochan = None
}
Anyway since there is mutating operation, it will always need 2 calls (1 for close and one for assignment of None).
I'm unhappy with the rule about variable scope in a try block not being shared with associated catch and finally blocks. Specifically it leads to code like the following:
var v: VType = null
try {
v = new VType()
}
catch {
case e => // handle VType constructor failure (can reference v)
}
finally {
// can reference v.
}
As opposed to:
try {
val v = new VType()
}
catch {
case e => // handle VType constructor failure (can reference v)
}
finally {
// can reference v.
}
Can anyone please explain or justify why this rule from Java persists?
and / or is there hope that this could change?
Thanks!
UPDATE
Many thanks for all the responses to date.
The consensus seems to imply "just get on with it" and I'm starting to conclude that perhaps technically what I want is either unsound, not worth the effort or hard to achieve.
I like Rex Kerr's answer but how would the original code above be wrapped in a method call without introducing a local var in the method body?
My own efforts weren't too good, using a by-name parameter to delay construction until safely in the try block works but still doesn't give me access to the constructed (or not) object in the catch or finally blocks.
Just "try" this ;)
val v = try { new VType() } catch { case e: Exception => /* ... */ }
In Scala, try is an expression, so it has a value.
You might be thinking about the problem the wrong way. Why do you want so much stuff in your try/catch/finally block? In your code,
try { val v = new VType() }
the exception could be thrown before you get v back, so you can't safely reference v. But if you can't reference v, then what can you do on the finally side that won't break or throw its own exception or have some other ill-defined behavior? What if you create v but fail to create w, but disposal requires having w as well? (Or doesn't?) It ends up being a mess.
But if you're coming from Java, there are a few things that can help you write try/catch/finally blocks in a sensible way.
One thing you can do is catch certain classes of exceptions and turn them into options instead:
def s2a(s: String) = try { Some(s.toInt) } catch { case nfe: NumberFormatException => None}
Another thing you can do is to create your own resource manager
def enclosed[C <: { def close() }](c: C)(f: C => Unit) {
try { f(c) } finally { c.close() }
}
enclosed(new FileInputStream(myFile))(fis => {
fis.read...
}
Or you can create your own shut-down-and-escape-safely method within another method:
val r = valuableOpenResource()
def attempt[F](f: => F) = {
try { f } catch { case re: ReasonableException => r.close() throw re }
}
doSomethingSafe()
attempt( doSomethingDangerous() )
doSomethingElseSafe()
r.close()
Between these different ways of handling things, I've not had much need to create vars to hold variables that I want to clean up later or otherwise deal with in catch or finally blocks.
How would this code work?
try
{
int i = 0;
// Do stuff...
Foo x = new Foo();
// Do more stuff...
Bar y = new Bar();
}
catch
{
// Print the values of i, x, and y.
}
What are the values of i, x, and y? Did y even get declared before we landed in the catch block?
The exception concept is not a subroutine of the try block, it is an alternate code flow. That makes at try-catch control block more like an "if anything untoward happens" then insert these (catch) lines in the current position of the try block, as needed.
With that in mind, it isn't clear if Val v = Type(); is going to be defined or not because the exception could (theoretically) be thrown before Val v = Type(); is evaluated. Yes, Val v is the first line in the block, but there are JVM errors which could be thrown before it.
Finally is another code construct which adds and alternate, but required, code flow the end of leaving the try-catch construct. Again, we have no idea how much (if any) of the try block was evaluated before the finally block was called, so we cannot depend on the declared variables within that block.
The only alternative left (now that we cannot use try block variables, due to their uncertainty of existence) is to use variable outside of the entire try-catch-finally construct for communications between the individual code blocks.
Does it suck? Maybe a little. Do we have anything that's better? Probably not. Putting the variable declarations outside of the block makes it obvious that the variables will have been defined prior to whatever control structure you process through in a try-catch-finally scenario.
If your main concern is that v should be immutable, you might get close to what you want with:
case class VType(name: String) {
// ... maybe throw an exception ...
}
val v = LazyVal(() => new VType())
try {
// do stuff with v
println(v.name) // implicitly converts LazyVal[VType] to VType
// do other unsafe stuff
} catch {
case e => // handle VType constructor failure
// can reference v after verifying v.isInitialized
} finally {
// can reference v after verifying v.isInitialized
if (v.isInitialized) v.safelyReleaseResources
}
where LazyVal is defined as
/**
* Based on DelayedLazyVal in the standard library
*/
class LazyVal[T](f: () => T) {
#volatile private[this] var _inited = false
private[this] lazy val complete = {
val v = f()
_inited = true
v
}
/** Whether the computation is complete.
*
* #return true if the computation is complete.
*/
def isInitialized = _inited
/** The result of f().
*
* #return the result
*/
def apply(): T = complete
}
object LazyVal {
def apply[T](f: () => T) = new LazyVal(f)
implicit def lazyval2val[T](l: LazyVal[T]): T = l()
}
It would be nice if we could use lazy val v = new VType(), but AFAIK there is no mechanism to safely determine whether a lazy val has been initialized.
Here's another alternative:
object Guard {
type Closing = {def close:Unit}
var guarded: Stack[Set[Closing]] = Stack()
def unapply(c: Closing) = {
guarded.push(guarded.pop + c)
Some(c)
}
private def close {println("Closing"); guarded.head.foreach{c => c.close}}
private def down {println("Adding Set"); guarded.push(Set())}
private def up {println("Removing Set"); guarded.pop}
def carefully(f: => Unit) {
down
try {f}
finally {close; up}
}
}
You can use it like this:
import Guard.carefully
class File {def close {println("Closed File")}}
class BadFile {def close {println("Closed Bad File")}; throw new Exception("BadFile failed")}
carefully {
val Guard(f) = new File
val Guard(g) = new File
val Guard(h) = new BadFile
}
which results in
Adding Set
Closing
Closed File
Closed File
java.lang.Exception: BadFile failed
So the first two files are created, then when the third constructor fails, the first two are automatically closed. All files are values.
Your example does not concretize why you need the finally clause. If VType is e.g. a resource that needs do be closed, you could do it one of the following ways.
1) You want to reference v after using it throws an exception:
try {
val v = new VType // may throw
try {
v.someThing // may throw
}
catch {
case ex => println("Error on doing something with v :" + v + ex) // or whatever
}
finally {
v.close()
}
}
catch {
case ex => println("Error on getting or closing v: " + ex) // v might not be constructed
}
2) You don't care about v in the catch clause:
try {
val v = new VType // may throw
try {
v.someThing // may throw
}
finally {
v.close()
}
}
catch {
case ex => println("Error on either operation: " + ex)
}
In either case, you get rid of the var.