对 Scala 方法调用约定感到困惑,特别是 Seq 上的 sum 函数

发布于 2024-10-29 09:06:08 字数 401 浏览 6 评论 0原文

我正在使用新的 Scala IDE(Eclipse 3.6.2 + Scala IDE 2.0.0 [Scala 2.9.0]),我尝试做一些简单的事情,如下所示:

(1 to 10).sum

效果很好,但我做了很多Groovy 最近也自动写道:

(1 to 10).sum()

第二个版本在 IDE 中给了我一个编译器错误,并显示以下消息:

方法 sum 没有足够的参数:(隐式数字:Numeric[B])B。未指定值参数 num。

我在 Scala API 上看到 sum 有两种版本,一种不带参数,一种带上面的隐式参数。我是否必须调用不带括号的零参数方法?

I was playing around with the new Scala IDE (Eclipse 3.6.2 + Scala IDE 2.0.0 [Scala 2.9.0]) and I tried to do something simple like this:

(1 to 10).sum

That works fine, but I've been doing a lot of Groovy also recently and I automatically wrote:

(1 to 10).sum()

This second version gives me a compiler error in the IDE with the following message:

not enough arguments for method sum: (implicit num: Numeric[B])B. Unspecified value parameter num.

I see on the Scala API that there are two versions of sum, one that takes no parameters and one that takes the implicit above. Do I have to call zero-argument methods without parentheses?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

违心° 2024-11-05 09:06:08

答案是如果您指定参数列表(即使用括号),那么必须指定其中的参数(或者更准确地说,是那些没有默认值的参数)。

如果您省略参数为隐式参数的非空参数列表上的括号,那么编译器可以为您注入它们(假设它可以在您的范围内明确找到相关的隐式:如第一个示例所示)

1 to 10 sum

如果您想自己传递参数(在本例中不需要这样做),那么您可以利用 Predef.implicitly 它基本上返回明确的范围内隐式值(假设有一个)。它们在这里的用途是:

(1 to 10).sum(implicitly[Numeric[Int]])
(1 to 10).sum[Int](implicitly)

这对于采用多个隐式参数的方法尤其重要,您可能只想覆盖其中一个参数(然后您可以隐式使用其他参数)。例如,在 scalaz 中,

aFoldable.sum(implicitly, myMonoid) //uses implicit Foldable but bespoke monoid

对于有关 scaladoc 用例的问题;这是一个虚拟条目,向您展示如何使用带有隐式参数列表的方法(否则可能会造成混淆)。此 scaladoc 条目的存在可以追溯到 这个臭名昭著的问题

The answer is that if you specify a parameter list (i.e. use the parens), then you must specify the parameters in it (or, more accurately, those without defaults).

If you omit the parens on a non-empty parameter list whose parameters are implicit, then the compiler can inject them for you (assuming it can find the relevant implicits unabmiguously in your scope: as in your first example)

1 to 10 sum

If you want to pass in the parameter yourself (there is no need to do so in this example), then you can take advantage of Predef.implicitly which basically returns the unabiguous in-scope implicit value (assuming there is one). Their use here would be:

(1 to 10).sum(implicitly[Numeric[Int]])
(1 to 10).sum[Int](implicitly)

This is particularly important in methods which take more than one implicit parameter, of which you might only wish to override one (you can then use implicitly for the others). For example, in scalaz

aFoldable.sum(implicitly, myMonoid) //uses implicit Foldable but bespoke monoid

For your question about the scaladoc use case; this is a phantom entry to show you how to use the (otherwise potentially confusing) method with the implicit parameter list. The existence of this scaladoc entry can be traced to this notorious question.

热风软妹 2024-11-05 09:06:08

只有一个版本。如果您仔细查看API,则一开始没有括号的条目说“ [用例]”。这是API文档中的合成重复条目,它更容易抓握。对于某些常见情况,用例基本上减少了完整条目。在此问题中有关此信息的更多信息: scaladoc [用例]

第二个呼叫的原因(... sum())失败是,尽管参数是隐式的,但它没有默认值。您只能在提供默认值时省略括号内的参数。尽管这听起来不合逻辑,但隐式论证的处理方式有所不同:您要么明确提供它们,因此您需要使用括号,或者省略它们(因为在范围中发现隐式),但是您还需要丢弃括号。这是为了促进更好的可读性,例如

def test(fun: Int => Int)(implicit s: String)

,您可以编写test {i => i}而不是test(i => i)()很尴尬。

There is only one version. If you carefully look at the API, the entry that has no parentheses says "[use case]" in the beginning. This is a synthetic duplicate entry in the API docs which is for easier grasping; the use-case entries are basically reduced full entries for some common scenarios. More on this in this question: Scaladoc [use case]

The reason why the second call (...sum()) fails is that although the argument is implicit, it doesn't have a default value. You can only omit arguments inside parentheses when default values are provided. Although this sounds illogical, implicit arguments are treated differently: either you supply them explicitly, then you need to use the parentheses, or you omit them (because an implicit is found in scope), but then you also need to drop the parentheses. This is to facilitate better readability, e.g.

def test(fun: Int => Int)(implicit s: String)

now you can write test { i => i } and not test(i => i)() which is awkward.

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