¿En qué se diferencian los futuros y las promesas de Clojure?

86

Tanto los futuros como las promesas se bloquean hasta que han calculado sus valores, entonces, ¿cuál es la diferencia entre ellos?

appshare.co
fuente
8
No estoy seguro de por qué el -1 en la pregunta, o ¿hay preguntas en las que no sabes la respuesta antes de preguntar ahora cosas malas?
SÓLO MI OPINIÓN correcta
¿No -1 ninguna de las respuestas? ¿Cómo podemos saber quién ha puesto -1 en una pregunta o respuesta?
appshare.co
Tú y yo no podemos, Zubair. Solo tengo curiosidad por saber quién puso un -1 en su pregunta dado que es una pregunta perfectamente razonable y definitivamente está relacionada con el tema de SO.
SÓLO MI OPINIÓN correcta

Respuestas:

54

Respondiendo en términos de Clojure, aquí hay algunos ejemplos del screencast de Sean Devlin :

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

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

Tenga en cuenta que en la promesa está entregando explícitamente un valor que selecciona en un cálculo posterior ( :freden este caso). El futuro, en cambio, se consume en el mismo lugar donde se creó. Se some-exprpresume que se lanza detrás de escena y se calcula en tándem (eventualmente), pero si permanece sin evaluar en el momento en que se accede a los bloques de hilo hasta que esté disponible.


editado para agregar

Para ayudar a distinguir mejor entre una promesa y un futuro, tenga en cuenta lo siguiente:

promesa

  1. Tu creas un promise . Ese objeto de promesa ahora se puede pasar a cualquier hilo.
  2. Continúas con los cálculos. Estos pueden ser cálculos muy complicados que involucran efectos secundarios, descarga de datos, entrada del usuario, acceso a la base de datos, otras promesas, lo que quiera. El código se parecerá mucho a su código de línea principal en cualquier programa.
  3. Cuando termines, puedes deliver enviar los resultados a ese objeto de promesa.
  4. Cualquier elemento que intente derefcumplir su promesa antes de que haya terminado con su cálculo se bloqueará hasta que haya terminado. Una vez que haya terminado y haya delivereditado la promesa, la promesa ya no se bloqueará.

futuro

  1. Tu creas tu futuro. Parte de tu futuro es una expresión de cálculo.
  2. El futuro puede o no ejecutarse al mismo tiempo. Se le podría asignar un hilo, posiblemente de un grupo. Podría simplemente esperar y no hacer nada. Desde tu perspectiva no puedes decir .
  3. En algún momento tú (u otro hilo) eres derefel futuro. Si el cálculo ya se completó, obtendrá los resultados. Si aún no se ha completado, bloquea hasta que lo haya hecho. (Es de suponer que si aún no ha comenzado, derefsignifica que comienza a ejecutarse, pero esto tampoco está garantizado).

Si bien podría hacer que la expresión en el futuro sea tan complicada como el código que sigue a la creación de una promesa, es dudoso que sea deseable. Esto significa que los futuros son realmente más adecuados para cálculos rápidos y en segundo plano, mientras que las promesas son realmente más adecuadas para rutas de ejecución grandes y complicadas. Además, las promesas parecen, en términos de cálculos disponibles, un poco más flexibles y orientadas hacia el creador de la promesa que hace el trabajo y otro hilo que cosecha la cosecha. Los futuros están más orientados a iniciar automáticamente un hilo (sin la sobrecarga fea y propensa a errores) y continuar con otras cosas hasta que usted, el hilo de origen, necesite los resultados.

SOLO MI CORRECTA OPINIÓN
fuente
Pero puede tener cualquier bloque de caluclation hasta que finalice una promesa O un futuro. es decir: (@a + @b) funcionará igual con un futuro y una promesa
appshare.co
2
Una promesa permite más flexibilidad, me parece. Creo una promesa. Paso esa promesa a otro hilo. Entonces puedo hacer muchos cálculos complicados, como esperar E / S, descargar datos de Internet, esperar la entrada del usuario, etc. Cuando todo está hecho, entrego la promesa con el valor resultante. Un futuro cubre una expresión-S. Supongo que podría ser una expresión en S muy, muy complicada, pero sería un poco ... rígida allí. Además, un futuro hace su trabajo automáticamente en un hilo (o grupo). Hacer lo mismo en una promesa significaría aún más trabajo.
SÓLO MI OPINIÓN correcta
FWIW, dado que una sola expresión s puede ser una llamada a una ruta de código arbitraria, no se trata necesariamente de la cantidad de código que se puede meter en la expresión. Entonces, en lugar de decir que una promesa es "más flexible", diría que su propósito es simplemente diferente. De lo contrario, ¿por qué tener ambos?
Geoff
2
Solo para que conste, el cuerpo de una futurellamada puede incluir N sexprs.
vemv
Esta explicación debería ser parte de Clojure Doc
Piyush Katariya
25

Tanto Future como Promise son mecanismos para comunicar el resultado de la computación asincrónica del Productor al Consumidor (es).

En el caso de Future, el cálculo se define en el momento de la creación de Future y la ejecución asíncrona comienza "lo antes posible". También "sabe" cómo generar un cálculo asincrónico.

En el caso de Promise, el cálculo , su hora de inicio y la invocación asincrónica [posible] se desacoplan del mecanismo de entrega. Cuando el resultado del cálculo está disponible, el Productor debe llamar deliverexplícitamente, lo que también significa que el Productor controla cuándo el resultado está disponible.

Para promesas, Clojure comete un error de diseño al usar el mismo objeto (resultado de la promisellamada) para producir ( deliver) y consumir ( deref) el resultado del cálculo . Estas son dos capacidades muy distintas y deben tratarse como tales.

Dimagog
fuente
@oskarkv Suponga que ha creado una promesa y se la ha dado a 3 clientes. Nada impide que uno de los clientes lo resuelva con un resultado falso y lo señale a otros dos clientes. Además, ya no podrá resolver esta promesa. Por el contrario, si tuvieras un par de promesa + resolutor, prometiste a tus clientes y mantuviste el resolutor para ti, este escenario se vuelve imposible. Para obtener más información, los términos de búsqueda sugeridos son "control de acceso basado en capacidades" y "seguridad basada en capacidades".
Dimagog
1
No estoy seguro de si promisesería conveniente acoplar la seguridad a un tipo de referencia tan simple (consulte su impl) como es. Los consumidores "malvados" son raros; nada le impide construir su propia abstracción sobre las promesas.
vemv
8
No se trata de seguridad, da la casualidad de que la programación basada en capacidades a menudo se describe en relación con la seguridad. Aquí se trata de la corrección del código. El término que se utiliza con frecuencia es "correcto por construcción" y la pregunta es "¿puede construir un programa incorrecto"? No a propósito, sino por accidente. Con un solo objeto Promise puede, mientras que con dos objetos separados no puede.
Dimagog
Sin embargo, no hay nada que le (defn undeliverable-promise [] (let [p (promise)] (reify clojure.lang.IDeref (deref [_] (deref p)) clojure.lang.IBlockingDeref (deref [_ ms val] (deref p ms val)) clojure.lang.IPending (isRealized [_] (.isRealized p)) clojure.lang.IFn (invoke [_ _] nil))))
impida
Señalar la diferencia de cómo se desacopla el mecanismo de cálculo hizo de esta publicación una explicación realmente concisa. ¡Gracias!
synthomat
3

Ya hay respuestas excelentes, así que solo agregue el resumen "cómo usar":

Ambos

Crear promesa o futuro devuelve una referencia de inmediato. Esta referencia se bloquea en @ / deref hasta que otro hilo proporcione el resultado del cálculo.

Futuro

Al crear el futuro, proporcionas un trabajo sincrónico por hacer. Se ejecuta en un hilo del grupo ilimitado dedicado.

Promesa

No das argumentos al crear una promesa. La referencia debe pasarse a otro hilo de 'usuario' que será deliverel resultado.

Grzegorz Luczywo
fuente
1

En Clojure, promise, future, y delayson promesa como objetos. Todos representan un cálculo que los clientes pueden esperar usando deref(o @). Los clientes reutilizan el resultado para que el cálculo no se ejecute varias veces.

Se diferencian en la forma en que se realiza el cálculo:

  • futureiniciará el cálculo en un hilo de trabajo diferente. derefse bloqueará hasta que el resultado esté listo.

  • delayrealizará el cálculo de forma perezosa, cuando el primer cliente utilice deref, o force.

  • promiseofrece la mayor flexibilidad, ya que su resultado se entrega de forma personalizada mediante el uso de deliver. Lo usa cuando ninguno de los dos futureo delaycoincide con su caso de uso.

Ernesto
fuente
-4

En primer lugar, a Promisees a Future. Creo que quieres saber la diferencia entre a Promisey a FutureTask.

A Futurerepresenta un valor que no se conoce actualmente pero que se conocerá en el futuro.

A FutureTaskrepresenta el resultado de un cálculo que ocurrirá en el futuro (tal vez en algún grupo de subprocesos). Cuando intentas acceder al resultado, si el cálculo aún no se ha realizado, se bloquea. De lo contrario, el resultado se devuelve de inmediato. No hay ninguna otra parte involucrada en el cálculo del resultado, ya que usted especifica el cálculo de antemano.

A Promiserepresenta un resultado que el prometidor entregará al prometido en el futuro. En este caso, usted es el prometido y el prometedor es el que le dio el Promiseobjeto. De manera similar a FutureTask, si intenta acceder al resultado antes de que Promisese haya cumplido, se bloqueará hasta que el prometedor cumpla con el Promise. Una vez Promisecumplido el, obtienes el mismo valor siempre e inmediatamente. A diferencia de a FutureTask, hay otra parte involucrada aquí, una que hizo el Promise. Que otra parte es responsable de hacer el cálculo y cumplir con el Promise.

En ese sentido, una FutureTaskes una que Promisete hiciste a ti mismo.

Abhinav Sarkar
fuente
¿Está seguro de que una promesa es un futuro? No puedo encontrar que implemente la interfaz. github.com/richhickey/clojure/blob/…
Mikael Sundberg
lo siento, presioné mal enter. Mi pregunta ha cambiado
Mikael Sundberg
Mi respuesta es en un sentido general, no en uno específico de Clojure.
Abhinav Sarkar
9
Responder una pregunta sobre Clojure con código Java parece un poco caprichoso.
SÓLO MI OPINIÓN correcta