как создать Scala API с маркером ошибки (например, Option.None), который можно связать через плоскую карту?

Недавно я попробовал вариант некоторых упражнений по параллелизму в Функциональное программирование в Scala (отличная книга, кстати. ., а издание с ранним доступом можно загрузить бесплатно!). Глава 7 посвящена созданию конструктора монадического типа Par[X], который позволяет разветвлять любое выражение типа X и запускать его параллельно в паре с ExectutorService

Моя попытка состояла в том, чтобы создать API, который позволял бы вызывающим сторонам отображать параллельные выражения (экземпляры параметризованного типа Par[X]) вместе. Я хотел что-то похожее на Option/Some/None, в котором, если один из результатов плоской карты в цепочке оказывается сбоем («Нет» в случае Option), то этот сбой, который «пузырится» до top, так что вызывающей стороне, создавшей цепочку, нужно только проверить, что возвращаемое значение верхнего уровня не является индикатором ошибки. (Надеюсь, то, что я хочу сделать, ясно из этого объяснения). В любом случае... Я столкнулся с проблемой построения индикатора ошибок.

Я попытался построить его двумя способами: как объект case и как класс case. В первом случае, объект case, я получил эту ошибку

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

Вот мой код для первого случая:

    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
    }

Затем я попытался использовать класс case, расширенный из Future[Nothing], например:

  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
  }

Это привело к следующей ошибке:

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

Если кто-то из вас, опытных разработчиков Scala API, может помочь найти решение, я был бы очень признателен!


person Chris Bedford    schedule 06.08.2015    source источник


Ответы (2)


Когда сообщения об ошибках относятся к

член get():V в java.util.concurrent.Future

они ссылаются на на get() метод Future без аргументов, который вы действительно забыли реализовать. Я предполагаю, что вы хотели, чтобы обе версии get() делали одно и то же. Вы просто должны четко заявить об этом. Например:

def get() = throw ...
def get(timeout: Long, units: TimeUnit) = get()
person Dan Getz    schedule 07.08.2015
comment
ой. глупая ошибка с моей стороны. спасибо что поймал! - person Chris Bedford; 07.08.2015

Этот ответ дополняет ответ Дэна, в котором он указал на мою ошибку (спасибо, Дэн!). Я надеюсь, что этот ответ/комментарий может помочь другим избежать подобных укусов. Когда я кодировал свой класс/объект case «Failure», я смотрел на класс case в исходной кодовой базе, которая реализовывала get() без аргументов Future таким образом, который не был очевиден для меня. Вот код:

      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
      }

В этом коде метод get() без аргументов, по-видимому, реализован неявно в результате того, что get является аргументом конструктора класса case... Класс отказа (таким образом, метод ошибки, с которым я столкнулся). Если бы я был умным, я бы сразу обратился к javadoc for Future, чтобы узнать, какие методы требуются.... но я основывал свое предположение о том, что требуется, на классе UnitFuture, и я упустил тот факт, что нет arg get( ) был частью этого класса. Ну что ж... живи и учись ;^) Надеюсь, это поможет другим не повторять мою ошибку.

person Chris Bedford    schedule 07.08.2015