How does it help to have a function as an argument?

Hi,

In functional programming, ability to pass a function as a method argument is considered very important.
But how does it actually help in writing a better program. A programmer can very well just invoke the function.
What advantages I get by passing function as argument?

It helps in all kinds of ways.
An early, very simple example you’ll see will be when using map() on a
collection. You pass it a function, and the collection applies it to the
collection’s contents.

“But couldn’t i just write a loop and do that myself?” Sometimes, perhaps,
but in OOP world sometimes you wouldn’t want the inner contents of
datastructures to be exposed or accessible externally by the programmer.
Or they might not be possible to access at the moment. A simple example in
scala that you’d have more trouble replicating without function arguments
would be Future.map(). The inner value might not even exist yet, so
there’s nothing the external programmer could call the function on even in
principle!

The datastructure needs to queue up the function until the value is ready,
and only then can the function be invoked with the value. The alternatives
to function arguments are pretty bleak, like polling for completeness
periodically. The code & structure to handle this is generally awful, and
not something i’d want to have to replicate for such essential
functionality.

-dave-

3 Likes

More simply, function parameters often result in far more concise, clear code – being able to do something like map() or filter() over a collection is a huge win. The code is shorter, easier to read, and has much less boilerplate; all three of those lead to quicker programming and fewer bugs.

This is true even for otherwise OO code. This is specifically why I got into C# about 15 years ago, and hated Java at the time – C# had first-class functions long before Java, and I found it unbearably irritating to write all the boilerplate necessary to do without first-class functions.

Note that, at this point, nearly every major language has first-class functions AFAIK – even Java eventually got a version of them. It’s not at all limited to FP…

2 Likes

reuse is an important benifit and is both about fragment reuse and template reuse.

FP enables fragment reuse (functions are reusable fragments).
FP also enables template reuse (functions with function parameters are reusable templates).

Below is an example illustrating template reuse endToEndTemplate is used twice (once with squareFunctionArgument and once with incrementFunctionArgument).

The template uses a producerFragment that reads from the console and a consumerFragment that writes to the console The example could also have illustrated fragment reuse by, for example, reading from a file and writing to a socket.

Sorry for the verbose names

trait FromAndTo[Z, Y] {

  val producerFragment: Unit => Z

  def consumerFragment(name: String): Y => Unit

  def endToEndTemplate(name: String)(fragmentParameter: Z => Y): Unit => Unit = { (u: Unit) =>
    val z = producerFragment(u)
    val y = fragmentParameter(z)
    consumerFragment(name)(y)
  }

}

import scala.io.StdIn.readInt

object FunctionalApp extends App {

  object readIntFromConsoleAndPrintFunctionAppliedToItToConsole extends FromAndTo[Int, Int] {
     override val producerFragment: Unit => Int = { (u: Unit) =>
       println("type an integer")
       readInt()
     }
     override def consumerFragment(name: String): Int => Unit = { j =>
       println(s"the value of $name applied to the integer is $j")
     }
  }

  import readIntFromConsoleAndPrintFunctionAppliedToItToConsole._

  val u: Unit = ()

  val squareFunctionArgument: Int => Int = {i => i * i}

  endToEndTemplate("square")(squareFunctionArgument)(u)

  val incrementFunctionArgument: Int => Int = {i => i + 1}

  endToEndTemplate("increment")(incrementFunctionArgument)(u)

}
$ scala FunctionalApp
type an integer
10
the value of square applied to the integer is 100
type an integer
10
the value of increment applied to the integer is 11
1 Like