为什么在Scala中区分方法和函数?

时间:2012-02-25 02:42:35

标签: scala

我一直在阅读Scala中的方法和函数。 Jim的post和Daniel的complement很好地解释了这些之间的差异。这就是我带给我的东西:

  • 函数是对象,方法不是;
  • 因此,函数可以作为参数传递,但方法不能;
  • 方法可以是类型参数化的,函数不能;
  • 方法更快。

我也了解defvalvar之间的区别。

现在我实际上有两个问题:

  1. 为什么我们不能参数化函数的apply方法来参数化函数?和
  2. 为什么函数对象不能调用该方法才能更快地运行?或者直接调用原始方法函数的调用者?
  3. 期待您的回答,并提前多多感谢!

2 个答案:

答案 0 :(得分:8)

1 - 参数化功能。

理论上,编译器可以参数化函数的类型;可以将其添加为功能。然而,这并非完全无足轻重,因为函数在其参数中具有逆变性,并且在其返回值中具有协变性:

trait Function1[+T,-R] { ... }

这意味着可以接受更多参数的另一个函数计为子类(因为它可以处理超类可以处理的任何内容),如果它产生一组较小的结果,那就没关系(因为它也会服从超类)以这种方式构建)。但你怎么编码

def fn[A](a: A) = a

在那个框架中?重点是返回类型等于传入的类型,无论该类型必须是什么。你需要

Function1[ ThisCanBeAnything, ThisHasToMatch ]

作为您的功能类型。如果你想要一个类型,那么“这可以是任何东西”由Any很好地表示,但是当原始类型丢失时你可以返回任何东西。这并不是说没有办法实现它,但它并不适合现有的框架。

2 - 功能速度。

这非常简单:函数是另一个对象的apply方法。您必须拥有该对象才能调用其方法。这比调用自己的方法总是慢(或至少没有更快),因为你已经拥有了自己。

作为一个实际问题,JVM现在可以很好地介绍功能;只要您主要使用您的方法或函数,而不是一遍又一遍地创建函数对象,性能通常没有差异。如果你深深地嵌套非常短的循环,你可能会发现自己创造了太多的功能;将它们移出嵌套循环外的val可以节省时间。但是,在你进行基准测试并知道那里存在瓶颈之前不要打扰;通常JVM做正确的事。

答案 1 :(得分:0)

考虑函数的类型签名。它明确说明了它需要什么类型。那么类型参数化apply()就会不一致。

函数是一个对象,必须创建,初始化然后进行垃圾回收。当调用apply()时,除了父对象之外,还必须抓取函数对象。