5

I have been reading about methods and functions in Scala. Jim's post and Daniel's complement to it do a good job of explaining what the differences between these are. Here is what I took with me:

  • functions are objects, methods are not;
  • as a consequence functions can be passed as argument, but methods can not;
  • methods can be type-parametrised, functions can not;
  • methods are faster.

I also understand the difference between def, val and var.

Now I have actually two questions:

  1. Why can't we parametrise the apply method of a function to parametrise the function? And
  2. Why can't the method be called by the function object to run faster? Or the caller of the function be made calling the original method directly?

Looking forward to your answers and many thanks in advance!

Community
  • 1
  • 1
Julien Gaugaz
  • 321
  • 3
  • 10

2 Answers2

8

1 - Parameterizing functions.

It is theoretically possible for a compiler to parameterize the type of a function; one could add that as a feature. It isn't entirely trivial, though, because functions are contravariant in their argument and covariant in their return value:

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

which means that another function that can take more arguments counts as a subclass (since it can process anything that the superclass can process), and if it produces a smaller set of results, that's okay (since it will also obey the superclass construct that way). But how do you encode

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

in that framework? The whole point is that the return type is equal to the type passed in, whatever that type has to be. You'd need

Function1[ ThisCanBeAnything, ThisHasToMatch ]

as your function type. "This can be anything" is well-represented by Any if you want a single type, but then you could return anything as the original type is lost. This isn't to say that there is no way to implement it, but it doesn't fit nicely into the existing framework.

2 - Speed of functions.

This is really simple: a function is the apply method on another object. You have to have that object in order to call its method. This will always be slower (or at least no faster) than calling your own method, since you already have yourself.

As a practical matter, JVMs can do a very good job inlining functions these days; there is often no difference in performance as long as you're mostly using your method or function, not creating the function object over and over. If you're deeply nesting very short loops, you may find yourself creating way too many functions; moving them out into vals outside of the nested loops may save time. But don't bother until you've benchmarked and know that there's a bottleneck there; typically the JVM does the right thing.

Community
  • 1
  • 1
Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
  • Thank you! I got the point regarding speed. If I understood you well, the problem for the type of a function `def fn[A](a:A) = a` is that it would need 3 types: the argument type, the return type, and the type parameter type. So why not using 3 type parameters like in `trait Typed1Function1[+T, +A, -R] extends Function1[A,R]`? Would that work? Or did I get you wrong? – Julien Gaugaz Feb 25 '12 at 11:59
  • @jullybobble - Kind of; the real problem is that you can't fit the types into `Function1` (expressing dependencies in the right way would be tricky if it's possible at all). – Rex Kerr Feb 25 '12 at 12:02
  • OK, I think I still don't really see the problem. But thanks for the effort! – Julien Gaugaz Feb 25 '12 at 12:14
  • I got the variance wrong, the correct signature would be `trait Typed1Function1[-T, -A, +R] extends Function1[A,R]` with `T` for the type parameter type, `A` the argument type and `R` the return type. – Julien Gaugaz Feb 25 '12 at 12:25
0

Think about the type signature of a function. It explicitly says what types it takes. So then type-parameterizing apply() would be inconsistent.

A function is an object, which must be created, initialized, and then garbage-collected. When apply() is called, it has to grab the function object in addition to the parent.

Ed Staub
  • 15,480
  • 3
  • 61
  • 91