8
votes

Créer un avenir sans commencer


2 commentaires

Peut-être que vous pourriez dire ce que vous devez accomplir?


Le fait que vous souhaitiez retarder le calcul me conduit à penser que vous comptez sur un changement d'état externe (effet secondaire). Si tel est le cas, utilisez des acteurs ...


8 Réponses :


7
votes

Vous pouvez faire quelque chose comme ceci xxx

ultérieur puis modifier:

Je pense que le motif que vous recherchez peut être encapsulé comme ceci: < Pré> xxx

Vous l'utiliseriez comme ceci: xxx


3 commentaires

Je suppose que succès mai commence ma fonction immédiatement. Et si je veux le démarrer plus tard en appelant succès (ou toute autre méthode) explicitement?


L'idée est belle, mais vous ne pouvez pas chaîner la latence l'Computation en tant que monade pour les expressions "pour", ce serait bien si un calcul est terminé, il a déclenché le suivant dans A pour expression


Vous feriez cela avec l'avenir du LatentComputation . Créez simplement une instance et retirez l'avenir et utilisez-le pour les compréhensions. Sinon, utilisez simplement une promesse d'accomplir cette



2
votes

Si vous avez trop envie de contrôler l'exécution, vous devriez peut-être utiliser des acteurs à la place?

ou, peut-être, vous devriez utiliser un promess au lieu d'un futur : un promesse peut être transmis sur les autres, pendant que vous Gardez-le à "remplir" cela plus tard.


1 commentaires

+1. Les gens ont commenté qu'elles sont sur la clôture des acteurs à terme à terme pour cette raison. Cependant, je trouve que quand je vais trop bien, c'est parce que je ne sais pas ce que je fais. Parfois, je ne sais même pas pourquoi je le fais. Et pourtant je continue à le faire.



2
votes

Il convient également de donner une fiche à Promess.comPletewith .

Vous savez déjà utiliser p.future onComplete mystuffe .

Vous pouvez déclencher cela d'un autre avenir à l'aide de p complewith f .


0 commentaires

3
votes

Vous pouvez toujours différer la création avec une fermeture, vous n'obtiendrez pas l'objet futur à l'avance, mais vous obtenez une poignée à appeler plus tard.

type DeferredComputation[T,R] = T => Future[R]

def deferredCall[T,R](futureBody: T => R): DeferredComputation[T,R] =
  t => future {futureBody(t)}

def deferredResult[R](futureBody: => R): DeferredComputation[Unit,R] =
  _ => future {futureBody}


0 commentaires

1
votes

Ou utilisez simplement des méthodes régulières qui renvoient des contrats à terme et tirent en série en utilisant quelque chose comme A pour la compréhension (évaluation séquentielle des sites d'appel)


0 commentaires

1
votes

Ce problème bien connu avec les bibliothèques standard Future: ils sont conçus de manière à ce qu'ils ne soient pas transparents de manière transparente, car ils évaluent avec impatience et mémoent leur résultat. Dans la plupart des cas d'utilisation, il s'agit de développeurs totalement fins et Scala a rarement besoin de créer un avenir non évalué.

Prendre le programme suivant: p>

f(Future(...), Future(...))


0 commentaires

1
votes

C'est un peu un piratage, car il n'a rien à voir avec la façon dont les travaux d'avenir, mais il suffit d'ajouter paresseux suffirait: Lazy Val F = Future {... // Ma fonction} Mais notez que cela est également en quelque sorte un changement de type, car chaque fois que vous y référez-le, vous devrez également déclarer la référence comme paresseuse ou elle sera exécutée.


0 commentaires

2
votes

Vous pouvez également définir une fonction qui crée et renvoie l'avenir, puis l'appelez:

// The functions that returns the future.
val double = (i: Int) => {
  val future = Future ({
    println(s"Start task $i")
    Thread.sleep(1000)
    i * 2
  })

  future.onComplete(_ => {
    println(s"Task $i ended")
  })

  future
}

val numbers = 1 to 20

numbers
  .map(i => (i, double))
  .grouped(5)
  .foreach(batch => {
    val result = Await.result( Future.sequence(batch.map{ case (i, callback) => callback(i) }), 5.minutes )
    println(result)
  })


0 commentaires