2015-12-20 3 views
1

Je trouve que je cours dans l'attribution de modèle ci-dessous et je ne peux pas le faire fonctionner ou regarder style sage sage.Gérer les contrats à terme avec for-comp, mais si les clauses rendent les choses difficiles

J'ai un pour la compréhension qui est de retour à terme, puis je construis mon modèle pour afficher dans une vue. Mais avant de renvoyer le résultat dans mon action, il m'arrive parfois de faire une branche en utilisant une clause if et de charger potentiellement plus de données.

Le code ci-dessous ne compile pas actuellement, que suggérez-vous que je fais pour que le code ci-dessous suive le style correct avec ce type de motif?

Il ne compile pas parce que l'intérieur pour compr est de retour un avenir [Option [Quelque chose]] mais j'ai défini c comme option [quelque chose]

for { 
    a <- fooService.getA() 
    b <- fooService.getB() 
} yield { 
    var c: Option[Something] = None 
    if(a.size > 0) { 
    c = for { 
     c <- fooService.getC() 
    } yield { 
     Some(c) 
    } 
    } 
} 
val model = FooModel(a, b, c) 
Ok(views.html.foo.show(model)) 

Mon modèle de vue est défini comme:

FooModel(a: A, b: B, c: Option[Something]) 

Répondre

3

Cela semble assez clair:

for { 
    a <- fooService.getA() 
    b <- fooService.getB() 
    c <- if (a.nonEmpty) fooService.getC() else Future.successful(None) 
} yield { 
    val model = FooModel(a, b, c) 
    Ok(views.html.foo.show(model)) 
} 

Extrait du if (a.nonEmpty) fooService.getC() else Future.successful(None) à une autre méthode ou s service si vous voulez.

+1

merci! Je développe lentement mes compétences de composition grâce à vous. – Blankman

0

Maintenant, il compile, mais avez-vous remarqué, que votre programme s'exécute séquentiellement?

object fooService{ 
    def getA() = { 
    Future{ 
     println("I'm getA") 
     for(i <- 1 to 10){ 
     println(".") 
     Thread.sleep(200) 
     } 
     "A" 
    } 
    } 
    def getB() = { 
    Future{ 
     println("I'm getB") 
     for(i <- 1 to 10){ 
     println(".") 
     Thread.sleep(200) 
     } 
     "B" 
    } 
    } 
} 

object Main { 
    def main(args: Array[String]) ={ 
    for { 
     a <- fooService.getA() 
     b <- fooService.getB() 
    } println(a + b) 

    Thread.sleep(4000) 
    } 
} 

C'est la sortie:

I'm getA 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
I'm getB 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
AB 

Et avec un peu de changement:

object fooService{ 
    def getA() = { 
    Future{ 
     println("I'm getA") 
     for(i <- 1 to 10){ 
     println(".") 
     Thread.sleep(200) 
     } 
     "A" 
    } 
    } 
    def getB() = { 
    Future{ 
     println("I'm getB") 
     for(i <- 1 to 10){ 
     println(".") 
     Thread.sleep(200) 
     } 
     "B" 
    } 
    } 
} 

object Main { 
    def main(args: Array[String]) ={ 
    val f1 = fooService.getA() 
    val f2 = fooService.getB() 
    for { 
     a <- f1 
     b <- f2 
    } println(a + b) 

    Thread.sleep(4000) 
    } 
} 

sortie:

I'm getA 
I'm getB 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
AB 
+0

C'est une très bonne observation. – tuxdna

+0

Pourquoi fait-il cela? Cela n'a pas de sens pour moi que vous deviez d'abord obtenir une référence pour cela et ensuite l'utiliser dans un for-comp? – Blankman

+0

Je suis toujours curieux de savoir pourquoi, mais en réalité, mon 1er appel dépend du 2ème appel. Sinon, je pourrais utiliser le zip aussi. – Blankman