web-dev-qa-db-fra.com

En quoi les futurs et promesses de Clojure diffèrent-ils?

Les contrats à terme et les promesses se bloquent jusqu'à ce qu'ils aient calculé leurs valeurs, alors quelle est la différence entre eux?

87
Yazz.com

Répondant en termes de Clojure, voici quelques exemples de screencast de Sean Devlin :

(def a-promise (promise))
(deliver a-promise :fred)

(def f (future (some-sexp)))
(deref f)

Notez que dans la promesse, vous fournissez explicitement une valeur que vous sélectionnez dans un calcul ultérieur (:fred dans ce cas). L'avenir, en revanche, se consomme au même endroit qu'il a été créé. Le some-expr est vraisemblablement lancé en arrière-plan et calculé en tandem (éventuellement), mais s'il reste non évalué au moment où il est accédé aux blocs de threads jusqu'à ce qu'il soit disponible.


modifié pour ajouter

Pour aider à mieux distinguer entre une promesse et un avenir, notez ce qui suit:

promettre

  1. Vous créez un promise. Cet objet de promesse peut désormais être transmis à n'importe quel thread.
  2. Vous continuez avec les calculs. Il peut s'agir de calculs très compliqués impliquant des effets secondaires, le téléchargement de données, la saisie par l'utilisateur, l'accès à la base de données, d'autres promesses - tout ce que vous voulez. Le code ressemblera beaucoup à votre code principal dans n'importe quel programme.
  3. Lorsque vous avez terminé, vous pouvez deliver les résultats de cet objet de promesse.
  4. Tout élément qui tente de deref votre promesse avant que vous ayez terminé votre calcul sera bloqué jusqu'à ce que vous ayez terminé. Une fois que vous avez terminé et que vous avez delivered la promesse, la promesse ne bloquera plus.

futur

  1. Vous créez votre avenir. Une partie de votre avenir est une expression de calcul.
  2. L'avenir peut ou non s'exécuter simultanément. Il pourrait être affecté un thread, éventuellement à partir d'un pool. Il pourrait simplement attendre et ne rien faire. De votre point de vue vous ne pouvez pas le dire.
  3. À un moment donné, vous (ou un autre thread) derefs le futur. Si le calcul est déjà terminé, vous en obtenez les résultats. Si ce n'est pas déjà fait, vous bloquez jusqu'à ce qu'il l'ait. (Vraisemblablement, s'il n'a pas encore commencé, derefing signifie qu'il commence à s'exécuter, mais cela aussi n'est pas garanti.)

Alors que vous pourriez rendre l'expression à l'avenir aussi compliquée que le code qui suit la création d'une promesse, il est peu probable que ce soit souhaitable. Cela signifie que les contrats à terme sont vraiment plus adaptés aux calculs rapides et en arrière-plan, tandis que les promesses sont vraiment plus adaptées aux grands chemins d'exécution compliqués. Trop, les promesses semblent, en termes de calculs disponibles, un peu plus flexibles et orientées vers le créateur de la promesse qui fait le travail et un autre fil récoltant la récolte. Les futurs sont plus orientés vers le démarrage automatique d'un thread (sans la surcharge laide et sujette aux erreurs) et la poursuite d'autres choses jusqu'à ce que vous - le thread d'origine - ayez besoin des résultats.

53

Future et Promise sont des mécanismes pour communiquer le résultat du calcul asynchrone du producteur au (x) consommateur (s).

Dans le cas de Future le calcul est défini au moment de la création Future et l'exécution asynchrone commence "ASAP ". Il "sait" également comment générer un calcul asynchrone.

Dans le cas de Promise le calcul , son heure de début et [possible] l'appel asynchrone sont découplés du mécanisme de livraison. Lorsque le résultat du calcul est disponible, le producteur doit appeler deliver explicitement, ce qui signifie également que le producteur contrôle lorsque le résultat devient disponible.

Pour Promesses Clojure fait une erreur de conception en utilisant le même objet (résultat de l'appel de promise) pour produire (deliver) et consommer (deref) le résultat du calcul . Ce sont deux capacités très distinctes et doivent être traitées comme telles.

24
Dimagog

Il y a déjà d'excellentes réponses, donc ajoutez seulement le résumé "comment utiliser":

Les deux

La création d'une promesse ou d'un futur renvoie immédiatement une référence. Cette référence se bloque sur @/deref jusqu'à ce que le résultat du calcul soit fourni par un autre thread.

Futur

Lors de la création du futur, vous fournissez un travail synchrone à effectuer. Il est exécuté dans un thread du pool illimité dédié.

Promesse

Vous ne donnez aucun argument lors de la création de la promesse. La référence doit être passée à un autre thread 'utilisateur' qui deliver le résultat.

3
Grzegorz Luczywo