Under what conditons do we need functions instead of methods

I have been looking at Scala 3’s polymorphic functions. I understand the basics and have tested some simple scenarios. However I cannot think up a case were I need a function. It seems that I can always use a polymorphic method and use eta-expansion to get a function. This seems to be true of Scala 2 also.

Can anyone show me a use-case were I need functions?

TIA

The question is a bit ambiguous, are you asking when functions, in general, are useful o when polymorphic functions are useful?

I am asking in general - when do I need functions (val) that methods (def) will not solve.

Sure, try to implement the map method on a List without using functions.

I hope I do not sound rude, but that is the best way I have to show why functions are useful, you use them on your every day Scala coding without noticing them, mostly due to lambda syntax and eta-expansion (the compiler will transform methods into functions automatically when needed).

Now, you are correct in that most of the time you would use methods (def) instead of functions for your own classes.

So let me see if I understand correctly. What you are saying is that in this case (defined in an object):

  def double(i:Int) = i*i

  def main(args: Array[String]): Unit =
    val l = (0 until 10).map(double)
    ()

the double method is converted to a function, correct?

What I am asking is, is their any situation where I need to explicitly use val because I cannot get away with using methods? Either by explicitly using the eta-expansion or the compiler doing fo me.

And BTW, I did not think you sounded rude. :sunglasses:

TIA

Yes, through a mechanism called eta-expansion.

Great, I was reading it before sending it and it sounded quite provocative.

Not really, since methods are more powerful than functions, see the links in the related FAQ entry.

However, the ability to say something like:

def doubleMap[A](data: List[A])(f: A => A): List[A] =
  data.map(f).map(f)

Imply that functions are values, they can be passed around, returned and stored on variables.
In any case, you may think that the parameter f in that method is a val, so that would be a use case; but I get your point.

There is one reason why you would prefer to have a val function instead of a method and it is that you are sure that you are going to use it like a function, for example, because you need to call methods on it like andThen.
For example, imagine you want to provide a method that receives a list of numbers and function from Int to Int, but instead of a normal map the results will be doubled after (I know, a contrived example but I hope it shows the idea); you could do it like:

object API {
  def mapAndDouble(data: List[Int])(f: Int => Int): List[Int]
    data.map(f).map(_ * 2)
}

However, mapping twice is quite expensive, it would better to apply both functions at the same time; so you do:

object API {
  def mapAndDouble(data: List[Int])(f: Int => Int): List[Int]
    data.map(f.andThen(_ * 2))
}

But, for whatever reason, you do not want the _ * 2 function to be created every time, you want to cache it; so you do:

object API {
  private val double: Int => Int = i => i * 2

  def mapAndDouble(data: List[Int])(f: Int => Int): List[Int]
    data.map(f andThen double)
}

Now, again this is very weird and in this case, it is not even clear why you would even want that.
During my 5 years using Scala I have only needed to that once and the snippet is somewhat complex so that is why I tried to come with a simpler example.

I get your point. I was forgetting that a function is an object and must be instantiated. I am assuming that when the compiler does eta-expansion it is in effect also instantiates a function.

Ok, so my conclusion is that functions are not strictly necessary and one can “get away” with methods only. Which brings me back to Scala 's polymorphic functions - also not strictly necessary. Your link above I had already read but the phrase " thanks to eta-expansion you rarely would need to define a function over a method" made me question what such a rare case would be.

BTW, your example reminds me of cases were we wish to construct pipelines of functions dynamically. May need this in the future.

Appreciate the feedback.

No, functions are extremely necessary for Scala. Basically, all the stdlib and most libraries are designed over the fact that functions exists and are values.
I may sound pedantic but this something that is important to be clear for you and future readers.

Now, it is correct to say that when modelling common business classes, you usually would use traditional methods over val functions. Nevertheless, it is probably that some (or many) of those methods will end up accepting functions as arguments: but then, you probably will use either lambdas or eta-expansion to pass those functions.

Anyways, I guess you already got the idea and I may start to sound repetitive, but I just wanted to finish this with a summary and a clarification.

1 Like

Just realized that my question is misleading, it should be “need to define functions” as opposed to “need to use functions”. Was looking at it from the client’s perspective (as you point out in your second paragraph).

Agree wholeheartedly. :sunglasses:

1 Like