web-dev-qa-db-fra.com

Fonction de passage de Scala avec argument

L'exemple Scala pour passer une fonction à une autre fonction manque le cas où la fonction passée (timeFlies) prend un 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))
  }
}

Comment puis-je faire fonctionner le code ci-dessus?

Edit: J'ai ajouté un x dans la seconde à la seconde pour clarifier l'objectif est de transmettre l'entier.

17
BAR

Vous pouvez le faire au moins de deux manières, en fonction de l'endroit où vous souhaitez exactement passer l'argument. La première consiste à conserver main comme vous l'avez fait. 

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))
  }
}

L'autre méthode consiste à transmettre le paramètre au moment du rappel, comme suit:

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)
  }
}

Notez que timeFlies a la signature (Int) => Unit, mais timeFlies(5) a la signature => Unit, en raison de application partielle . Cela signifie que vous pouvez appliquer le paramètre pour créer automatiquement une fonction qui prend moins de paramètres. oncePerSecond doit savoir dans sa signature si vous avez déjà appliqué le paramètre Int au rappel ou non. 

Les deux méthodes sont utiles pour différents cas d'utilisation. La première façon permet à oncePerSecond de ne pas avoir à connaître les paramètres du rappel. La deuxième façon vous permet de changer la valeur de x à chaque fois dans la boucle si vous le souhaitez.

22
Karl Bielefeldt

Le type de retour de timeFlies sera Unit et non Function. Peut-être que vous vouliez dire: 

oncePerSecond(() => timeFlies(5))
3
John

Le paramètre callback: () => Unit est une fonction de paramètre zéro qui renvoie Unit. Vous devriez en faire un paramètre appel par nom (quelque chose qui vaut Unit):

def oncePerSecond(callback: => Unit) = ...
0
Michael Zajac