Нужна помощь с Scala - PullRequest
       4

Нужна помощь с Scala

1 голос
/ 01 марта 2011

Может ли кто-нибудь помочь мне понять этот код?Я ничего не знаю о Scala и не слышал об этом.

def maxSubseq(l: List[Int]) = l.scanRight(Nil : List[Int]) {
    case (el, acc) if acc.sum + el < 0 => Nil
    case (el, acc) => el :: acc
} max Ordering.by((_: List[Int]).sum)

def biggestMaxSubseq(l: List[Int]) = l.scanRight(Nil : List[Int]) {
    case (el, acc) if acc.sum + el < 0 => Nil
    case (el, acc) => el :: acc
} max Ordering.by((ss: List[Int]) => (ss.sum, ss.length))

def biggestMaxSubseq[N](l: List[N])(implicit n: Numeric[N]) = {
    import n._
    l.scanRight(Nil : List[N]) {
        case (el, acc) if acc.sum + el < zero => Nil
        case (el, acc) => el :: acc
    } max Ordering.by((ss: List[N]) => (ss.sum, ss.length))
}

def linearBiggestMaxSubseq[N](l: List[N])(implicit n: Numeric[N]) = {
    import n._
    l.scanRight((zero, Nil : List[N])) {
        case (el, (acc, _)) if acc + el < zero => (zero, Nil)
        case (el, (acc, ss)) => (acc + el, el :: ss)
    } max Ordering.by((t: (N, List[N])) => (t._1, t._2.length)) _2
}

Может ли этот код быть реализован на Java?

1 Ответ

7 голосов
/ 01 марта 2011

Конечно, это может быть реализовано на Java.Это потребует больше усилий, хотя.Давайте рассмотрим некоторые моменты здесь.

def linearBiggestMaxSubseq[N](l: List[N])(implicit n: Numeric[N]) = {

Здесь объявляется метод, который получает List из N и неявный параметр Numeric[N].Неявные параметры обычно выводятся самим компилятором путем поиска определенных мест для объявлений, которые соответствуют обязательному параметру - почти как внедрение зависимостей.

В этом случае Numeric[N] - это класс, который обеспечивает базовые математические операциии для которых есть экземпляры для всех числовых типов, представленных в стандартной библиотеке.Единственные вещи, которые этот метод использует из Numeric, это plus и zero.

Java не имеет последствий, поэтому эквивалентный Java API будет немного более громоздким в использовании, требуя его передачидополнительный параметр.

Кроме того, я не помню ни одного эквивалента Numeric в Java.java.lang.Number не предоставляет методы, подобные тем, которые встречаются в BigInt и BigDecimal.Вы должны написать свой собственный эквивалент Numeric, а затем написать экземпляры, чтобы охватить все числовые типы, и тогда клиентский код должен был бы передать экземпляр явно.Если в Java есть альтернатива тому, чтобы пойти на все эти усилия, я бы хотел услышать об этом.

    import n._

Все, что это делает, это позволяет коду делать acc + el вместо n.plus(acc, el), иzero вместо n.zero.Как это происходит, выходит за рамки этого вопроса.

l.scanRight((zero, Nil : List[N])) {

В Java нет эквивалента scanRight.Вы должны превратить это в цикл while, но это не особенно сложно сделать.scanRight будет проходить по списку справа налево (хотя я не вижу причин, почему код делает это справа налево вместо более простого и эффективного слева направо).

По мере его обходасписок (l), он вызовет функцию, передающую два параметра: текущий элемент и «аккумулятор».Здесь аккумулятор представляет собой Pair, мелкий объект с парой геттеров и сеттеров для двух элементов в контейнере.В первый раз эта пара инициализируется с помощью zero и Nil (пустой список).

Метод, вызываемый scanRight, должен возвращать что-то того же типа, что и аккумулятор -поэтому, передав Pair[N, List[N]], он должен вернуть новый Pair[N, List[N]].

Наконец, scanRight создаст коллекцию с результатами метода, который он вызывает.

    case (el, (acc, _)) if acc + el < zero => (zero, Nil)
    case (el, (acc, ss)) => (acc + el, el :: ss)

В этом коде много совпадений, которые должны быть заменены серией операторов if / else.Подробно, но не особенно хлопотно.

В данном конкретном случае (el, (acc, _)) и (ec, (acc, ss)) - это просто передаваемые параметры.Они могут воплощать тесты, но здесь они этого не делают.Единственный проводимый тест - acc + el < zero.Если это так, он возвращает (zero, Nil), если нет, он возвращает (acc + el, el :: ss).Как я уже говорил ранее, Nil - пустой список.Здесь el :: ss возвращает новый список с el, добавленным перед списком ss.

} max Ordering.by((t: (N, List[N])) => (t._1, t._2.length)) _2

По крайней мере, числовые классы Java обычно реализуют Comparable, даже если онине реализуйте интерфейс, обеспечивающий числовые операции.Существует множество Ordering.by экземпляров, для каждого из которых потребуется эквивалент Comparator или какое-то другое специальное решение.

В любом случае это вернет максимальный элемент (max), используя Ordering (эквивалент Comparator), в котором сначала рассматривается значение первого элемента пары, а длина второго элемента пары (который является списком).

Наконец, _2 отбросит первый элемент пары и вернет второй элемент.

Это самый сложный из всех методов.Предыдущие являются более простыми, за счет того, что они менее универсальны и эффективны.

Итак, версия Java, конечно, будет более многословной, но, кроме проблемы Numeric, она должна быть довольно простой.написать.Опять же, проблема Numeric довольно критична.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...