0

I recently tried a variation on some of the concurrency exercises in Functional Programming in Scala (great book, btw.. and early access edition is downloadable free!). Chapter 7 involves creating a monadic type constructor Par[X], which enables any expression of type X to be forked off and run in parallel when paired with an ExectutorService

My attempted variation was to create an API that allowed callers to flatmap parallel expressions (instances of the parameterized type Par[X]) together. I wanted something with a similar flavor to Option/Some/None wherein if one of the flatmap results in the chain happens to be a failure (a 'None' in the case of Option), then that failure that 'bubbles up' to the top, so that the caller that constructed the chain only needs to check that the top level return value is not the error sentinel. (Hope what I want to do is clear from this explanation). Anyway... I ran into a problem constructing the error sentinel.

I tried to contruct it two ways, as a case object, and as a case class. In the first instance, the case object, I got this error

    Object creation impossible since member get():V in java.util.concurrent.future is not defined.

Here is my code for the first case:

    case object Failure extends Future[Nothing] {
    def isDone = true

    // why is compiler telling me i'm not defining this, when def'n is below?
    def get(timeout: Long, units: TimeUnit) =  
        throw new NoSuchElementException("nothing to get from failure")

    def isCancelled = false

    def cancel(evenIfRunning: Boolean): Boolean = false
    }

I then tried using case class which extended from Future[Nothing], like so:

  case class Failure2 extends Future[Nothing] {
    def isDone = true

    def get(timeout: Long, units: TimeUnit) =  throw new NoSuchElementException("nothing to get from failure")

    def isCancelled = false

    def cancel(evenIfRunning: Boolean): Boolean = false
  }

This resulted in the following error:

class Failure2 must be declared abstract or implement abstract member get():V in java.util.concurrent.future 

If any of you expert Scala API builders can help guide my to a solution I would be very grateful !

Chris Bedford
  • 2,560
  • 3
  • 28
  • 60

2 Answers2

0

When the error messages refer to

member get():V in java.util.concurrent.Future

they're referring to the get() method of Future with no arguments, which you indeed forgot to implement. I'm guessing you wanted both versions of get() to do the same thing. You just have to be explicit about that. For example:

def get() = throw ...
def get(timeout: Long, units: TimeUnit) = get()
Dan Getz
  • 8,774
  • 6
  • 30
  • 64
0

This answer supplements Dan's answer, in which he pointed out my mistake (thanks, Dan!). I'm hoping this answer/comment might help others avoid being similarly bitten. When I coded up my 'Failure' case class/object I was looking at a case class in the original code base that implemented the no argument get() of Future in a way that wasn't obvious to me. Here is the code:

      private case class UnitFuture[A](get: A) extends Future[A] {
        def isDone = true

        def get(timeout: Long, units: TimeUnit) = get

        def isCancelled = false

        def cancel(evenIfRunning: Boolean): Boolean = false
      }

In this code the no argument get() method seems to be implemented implicitly as a result of get being an argument to the case class constructor... I didn't realize this method was even there, so I neglected to implement it in my Failure class (thus the error method that I encountered). If I was smart I would have gone right to the javadoc for Future to see what methods were required.... but I based my assumption of what was required on the 'UnitFuture' class, and I missed the fact that no arg get() was part of that class. Oh well.. live and learn ;^) Hope this helps others not repeat my error.

Chris Bedford
  • 2,560
  • 3
  • 28
  • 60