需要 Scala 帮助

发布于 2024-10-19 10:56:55 字数 1091 浏览 2 评论 0原文

谁能帮我理解这段代码?我对 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

£噩梦荏苒 2024-10-26 10:56:55

当然,它可以用Java实现。不过,这需要付出更多努力。让我们看看这里的一些要点。

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

这声明了一个接收 NList 和隐式参数 Numeric[N] 的方法。隐式参数通常由编译器本身通过查找某些位置来查找与所需参数匹配的声明来派生——几乎就像依赖注入一样。

在本例中,Numeric[N] 是一个提供基本数学运算的类,并且标准库中提供了所有数字类型的实例。此方法仅使用 Numeric 中的 pluszero

Java 没有隐式,因此等效的 Java API 使用起来会比较麻烦,需要传递一个附加参数。

另外,我不记得 Java 中有任何与 Numeric 等效的东西。 java.lang.Number 不提供诸如 BigIntBigDecimal 中的方法。您必须编写自己的 Numeric 等效项,然后编写实例来涵盖所有数字类型,然后客户端代码必须显式传递该实例。如果 Java 中有一种替代方法可以代替所有这些努力,我很想听听。

    import n._

所有这一切都是允许代码执行 acc + el 而不是 n.plus(acc, el),以及 zero 而不是 >n.0。它如何做到这一点超出了本问题的范围。

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

Java 中没有等效的 scanRight 功能。您必须将其转换为 while 循环,但这并不是特别难。 scanRight 将从右到左遍历列表(尽管我看不出代码从右到左而不是更简单、更高效的从左到右的原因)。

当它遍历列表 (l) 时,它将调用一个传递两个参数的函数:当前元素和一个“累加器”。这里的累加器是一个Pair,一个浅对象,具有一对包含中两个元素的 getter 和 setter。第一次,该对使用 zeroNil(空列表)进行初始化。

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 是否 acc + el 零。如果是,则返回(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 等效项或其他一些临时解决方案。

无论如何,这将使用 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.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文