Scala Passing Function with Argument

2020-06-08 03:46发布

问题:

The Scala example for passing a function to another function lacks the case where the passed function (timeFlies) takes an argument (x).

object Timer {
  def oncePerSecond(callback: (Int) => Unit) {
    while (true) { callback(x); Thread sleep 1000 }
  }
  def timeFlies(x: int) {
    println("time flies like an arrow...")
  }
  def main(args: Array[String]) {
    oncePerSecond(timeFlies(5))
  }
}

How can I make the above code work?

Edit: I added an x in the oncepersecond to clarify the goal is to pass the integer.

回答1:

There are at least two ways you can do it, depending on where exactly you want to pass the argument in. The first way is where you keep main like you had it.

object Timer {
  def oncePerSecond(callback: => Unit) {
    while (true) { callback; Thread sleep 1000 }
  }
  def timeFlies(x: Int) {
    println("time flies like an arrow...")
  }
  def main(args: Array[String]) {
    oncePerSecond(timeFlies(5))
  }
}

The other method is to pass the parameter in at the point of the callback, like this:

object Timer {
  def oncePerSecond(callback: (Int) => Unit) {
    val x = 5
    while (true) { callback(x); Thread sleep 1000 }
  }
  def timeFlies(x: Int) {
    println("time flies like an arrow...")
  }
  def main(args: Array[String]) {
    oncePerSecond(timeFlies)
  }
}

Note that timeFlies has the signature (Int) => Unit, but timeFlies(5) has the signature => Unit, because of partial application. This basically means you can apply the parameter to automatically create a function that takes fewer parameters. oncePerSecond needs to know in its signature if you've already applied the Int parameter to the callback or not.

Both methods are useful for different use cases. The first way lets oncePerSecond not have to know about the callback's parameters. The second way lets you change the value of x every time through the loop if you want.



回答2:

The return type of timeFlies will be Unit, not Function. Perhaps you meant:

oncePerSecond(() => timeFlies(5))


回答3:

oncePerSecond(() => timeFlies(5))

or

def oncePerSecond(callback: => Unit) {...



回答4:

The parameter callback: () => Unit is a zero-parameter function that returns Unit. You should make it call-by-name parameter (something that evaluates to Unit):

def oncePerSecond(callback: => Unit) = ...