需要 Scala 帮助
谁能帮我理解这段代码?我对 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实现吗?
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]) = {
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当然,它可以用Java实现。不过,这需要付出更多努力。让我们看看这里的一些要点。
这声明了一个接收
N
的List
和隐式参数Numeric[N]
的方法。隐式参数通常由编译器本身通过查找某些位置来查找与所需参数匹配的声明来派生——几乎就像依赖注入一样。在本例中,
Numeric[N]
是一个提供基本数学运算的类,并且标准库中提供了所有数字类型的实例。此方法仅使用Numeric
中的plus
和zero
。Java 没有隐式,因此等效的 Java API 使用起来会比较麻烦,需要传递一个附加参数。
另外,我不记得 Java 中有任何与
Numeric
等效的东西。java.lang.Number
不提供诸如BigInt
和BigDecimal
中的方法。您必须编写自己的Numeric
等效项,然后编写实例来涵盖所有数字类型,然后客户端代码必须显式传递该实例。如果 Java 中有一种替代方法可以代替所有这些努力,我很想听听。所有这一切都是允许代码执行
acc + el
而不是n.plus(acc, el)
,以及zero
而不是>n.0
。它如何做到这一点超出了本问题的范围。Java 中没有等效的
scanRight
功能。您必须将其转换为while
循环,但这并不是特别难。scanRight
将从右到左遍历列表(尽管我看不出代码从右到左而不是更简单、更高效的从左到右的原因)。当它遍历列表 (
l
) 时,它将调用一个传递两个参数的函数:当前元素和一个“累加器”。这里的累加器是一个Pair
,一个浅对象,具有一对包含中两个元素的 getter 和 setter。第一次,该对使用zero
和Nil
(空列表)进行初始化。由
scanRight
调用的方法应该返回与累加器类型相同的内容 - 因此,当传递一个Pair[N, List[N]]
时,它应该返回一个新的Pair[N, List[N]]
。最后,
scanRight
将创建一个包含其所调用方法的结果的集合。此代码中有大量匹配的内容,必须用一系列
if
/else
语句替换。冗长,但不是特别麻烦。在这种特殊情况下,
(el, (acc, _))
和(ec, (acc, ss))
只是传递的参数。它们可以包含测试,但是在这里,它们没有。唯一进行的测试是 acc + el是否
acc + el
零。如果是,则返回
(zero, Nil)
,如果不是,则返回(acc + el, el :: ss)
。正如我之前所说,Nil
是一个空列表。这里,el :: ss
返回一个新列表,其中el
被添加到列表ss
之前。至少 Java 的数字类通常实现 Comparable,即使它们没有实现提供数字操作的接口。有许多
Ordering.by
实例,每个实例都需要一个Comparator
等效项或其他一些临时解决方案。无论如何,这将使用
Ordering
(相当于Comparator
)返回最大元素 (max
),该排序首先考虑该对的第一个元素,以及该对的第二个元素的长度(这是一个列表)。最后,
_2
将丢弃该对的第一个元素并返回第二个元素。这是所有方法中最复杂的。前面的方法更简单,但代价是通用性和效率较低。
因此,Java 版本肯定会更加冗长,但除了
Numeric
问题之外,编写起来应该非常简单。话又说回来,Numeric
问题非常关键。Sure, it can be implemented in Java. It will require more effort, though. Let's see some points here.
This declares a method which receives a
List
ofN
, and an implicit parameterNumeric[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 fromNumeric
areplus
andzero
.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 inBigInt
andBigDecimal
. You'd have to write your own equivalent ofNumeric
, 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.All this does is allow the code to do
acc + el
instead ofn.plus(acc, el)
, andzero
instead ofn.zero
. How it does that is beyond the scope of this question.There's no
scanRight
equivalent in Java. You'd have to turn this into awhile
loop, but it isn't particularly hard to do. AscanRight
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 aPair
, a shallow object with a pair of getters and setters for two elements in contains. The first time around, this pair is initialized withzero
andNil
(an empty list).The method called by
scanRight
is supposed to return something of the same type as the accumulator -- so, being passed aPair[N, List[N]]
, it should return a newPair[N, List[N]]
.Finally,
scanRight
will create a collection with the results of the method it is calling.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 whetheracc + 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 withel
prepended to the listss
.At least Java's numeric classes usually implement
Comparable
, even if they do not implement an interface providing numeric operations. There are manyOrdering.by
instances, each of which will require aComparator
equivalent or some other ad hoc solution.At any rate, this will return the maximum element (
max
), using anOrdering
(equivalent toComparator
) 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, theNumeric
issue is pretty critical.