Need help with Scala
Could anyone help me to understand this code? I don't know anything about Scala nor heard about it.
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]) =开发者_如何学Go {
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
}
Could this code be implemented in Java?
Sure, it can be implemented in Java. It will require more effort, though. Let's see some points here.
def linearBiggestMaxSubseq[N](l: List[N])(implicit n: Numeric[N]) = {
This declares a method which receives a List
of N
, and an implicit parameter Numeric[N]
. Implicit parameters are usually derived by the compiler itself by looking up certain places for declarations that match the required parameter -- almost like a dependency injection.
In this case, Numeric[N]
is a class that provides basic mathematical operations, and for which there are instances for all numeric types provided in the standard library. The only things this method uses from Numeric
are plus
and zero
.
Java doesn't have implicits, so the equivalent Java API would be a bit more cumbersome to use, requiring one to pass an additional parameter.
Also, I don't recall any equivalent to Numeric
in Java. java.lang.Number
doesn't provide methods such as those found in BigInt
and BigDecimal
. You'd have to write your own equivalent of Numeric
, and then write instances to cover all numeric types, and then the client code would have to pass the instance explicitly. If there's an alternative in Java to going to all that effort, I'd love to hear about it.
import n._
All this does is allow the code to do acc + el
instead of n.plus(acc, el)
, and zero
instead of n.zero
. How it does that is beyond the scope of this question.
l.scanRight((zero, Nil : List[N])) {
There's no scanRight
equivalent in Java. You'd have to turn this into a while
loop, but it isn't particularly hard to do. A scanRight
will traverse the list from right to left (though I don't see any reason why the code does it right to left instead of the more easy and efficient left to right).
As it traverses the list (l
), it will call a function passing two parameters: the current element, and an "accumulator". Here the accumulator is a Pair
, a shallow object with a pair of getters and setters for two elements in contains. The first time around, this pair is initialized with zero
and Nil
(an empty list).
The method called by scanRight
is supposed to return something of the same type as the accumulator -- so, being passed a Pair[N, List[N]]
, it should return a new Pair[N, List[N]]
.
Finally, scanRight
will create a collection with the results of the method it is calling.
case (el, (acc, _)) if acc + el < zero => (zero, Nil)
case (el, (acc, ss)) => (acc + el, el :: ss)
Plenty of matter matching in this code, which will have to be replaced by a series of if
/else
statements. Verbose, but not particularly troublesome.
In this particular case, (el, (acc, _))
and (ec, (acc, ss))
are just the parameters being passed. They could embody tests, but, here, they don't. The only test being made is whether acc + el < zero
. If so, it returns (zero, Nil)
, if not it returns (acc + el, el :: ss)
. As I said earlier, Nil
is an empty list. Here, el :: ss
returns a new list with el
prepended to the list ss
.
} max Ordering.by((t: (N, List[N])) => (t._1, t._2.length)) _2
At least Java's numeric classes usually implement Comparable
, even if they do not implement an interface providing numeric operations. There are many Ordering.by
instances, each of which will require a Comparator
equivalent or some other ad hoc solution.
At any rate, this will return the maximum element (max
), using an Ordering
(equivalent to Comparator
) which considers first the value of the first element of the pair, and the length of the second element of the pair (which is a list).
Finally, _2
will discard the first element of the pair and return the second element.
This is the most complex of all methods. The previous ones are more simpler, at the cost of being less generic and efficient.
So, the Java version will be more verbose, for sure, but aside the Numeric
issue, should be pretty straight-forward to write. Then again, the Numeric
issue is pretty critical.
精彩评论