2009-12-15 14 views
2

J'ai vu un exemple delayed dans "Beginning Scala" de David Pollak. J'ai essayé de l'adapter, par essais et erreurs. Voici ce que j'ai:Comment définiriez-vous un paramètre retardé (par nom) qui accepte une fonction qui prend des paramètres?

def sayhello() = { 
    println("hello") 
} 

def delaying(t: => Unit):Unit = { 
    println("before call") 
    t 
    println("after call") 
} 

delaying(sayhello()) 

Comment décririez-vous retarder une fonction/méthode qui prend des paramètres? Pourquoi ne puis-je pas utiliser les parenthèses lorsque j'appelle t? Où puis-je trouver plus de documentation sur les fonctions de retardement?

+0

@DerekMahar fait. S'il vous plaît, retirez votre commentaire (je vais retirer le mien alors aussi). –

Répondre

5

t ne doit pas nécessairement être une valeur de fonction. C'est simplement n'importe quelle valeur passée par nom qui évalue à Unit.

Lorsque vous définissez t dans la fonction delaying, vous n'appelez pas explicitement la fonction transmise en tant que paramètre. En l'indiquant, vous forcez l'évaluation du paramètre passé par le nom, ce qui signifie que sayhello() est évalué à ce moment.

Il n'y a aucune raison que vous ne pouvez pas utiliser les paramètres dans les fonctions des paramètres transmis par nom:

def say(word: String) { 
    println(word) 
} 

def delaying(t: => Unit) { 
    println("before call") 
    t 
    println("after call") 
} 

delaying(say("hello")) 

Le seul moment où vous attacher des paramètres à la t l'intérieur delaying serait si son type de retour était (pas Unit mais) un type de fonction prenant des paramètres.

+0

Puis-je transmettre quelque chose qui renvoie un autre type que 'Unit'? Ou cela prend des paramètres? Si oui, pouvez-vous poster un exemple? – Geo

+0

Geo, oui, vous pouvez passer n'importe quelle sorte de valeur dans un paramètre par nom. J'ai déjà posté un exemple dans ma réponse de quelque chose qui prend des paramètres: voir ma fonction 'say'. –

+0

Oh! Pardon. Je pense que j'ai filtré mentalement que :) – Geo

1

Depuis que j'ai une mémoire terrible et la réponse ne fournit pas un exemple comment déclarer effectivement un paramètre par nom qui donne une fonction qui prend un ou plusieurs arguments, je suis venu avec ceci:

object DelayedEvalTest { 

    private class DelayedFunction extends Function1[Int,Unit] { 

     override def apply(x:Int) : Unit = {} 

     println("function created") 
    } 

    private def eval(eval:Boolean, op : Int => Unit) { 
     println("in eval()") 
     if (eval) { 
      op(42) 
     } 
    } 

    private def evalDelayed(eval:Boolean, op : => Int => Unit) { 
     println("in evalDelayed()") 
     if (eval) { 
      op(42) 
     } 
    } 

    def main(args:Array[String]) { 
     eval(false , new DelayedFunction()) 
     evalDelayed(false , new DelayedFunction()) 
    } 

}