2012-03-08 13 views
6

Estoy implementando un marco de FRP en Scala y parece que me he encontrado con un problema. Motivado por un poco de pensamiento, esta pregunta me decidió restringir la interfaz pública de mi marco de modo Comportamientos solamente pudieron ser evaluados en el 'presente' es decir:Implementación de instantáneas en FRP

behaviour.at(now) 

Esto también está en consonancia con la hipótesis de Conal en el papel de Fran que Los comportamientos solo se evalúan/prueban cada vez más. Se restringe transformaciones en los comportamientos pero por lo demás nos encontramos en enormes problemas con los comportamientos que representan una cierta entrada:

val slider = Stepper(0, sliderChangeEvent) 

Con este comportamiento, la evaluación de los valores futuros sería incorrecto y la evaluación de los valores del pasado requeriría una cantidad ilimitada de memoria (todas las ocurrencias usadas en el evento 'slider' tendrían que ser almacenadas).

Tengo problemas con la especificación para el funcionamiento de "instantánea" en Comportamientos dada esta restricción. Mi problema se explica mejor con un ejemplo (usando el control deslizante se mencionó anteriormente):

val event = mouseB // an event that occurs when the mouse is pressed 
val sampler = slider.snapshot(event) 
val stepper = Stepper(0, sampler) 

mi problema aquí es que si se ha producido el evento 'mouseB' cuando se ejecuta este código, entonces el valor actual de 'paso a paso' voluntad ser la última 'muestra' de 'control deslizante' (el valor en el momento en que ocurrió la última ocurrencia). Si la hora de la última ocurrencia está en el pasado, consecuentemente terminaremos evaluando el 'control deslizante' usando un tiempo pasado que rompe el conjunto de reglas anterior (y su suposición original). Puedo ver un par de maneras de resolver esto:

  1. Nos 'registro' el pasado (mantener la suspensión de todas las ocurrencias del pasado en un evento) que permite la evaluación de los comportamientos con los tiempos pasados ​​(usando una cantidad ilimitada de memoria)
  2. Modificamos 'snapshot' para tomar un argumento de tiempo ("sample after this time") y aplicamos ese tiempo> = now
  3. En un movimiento más loco, podríamos restringir la creación de objetos FRP a la configuración inicial de un programe de alguna manera y solo empiece a procesar eventos/entrada una vez que se complete esta configuración

También podría simplemente no implementar 'sample' o eliminar 'stepper'/'switcher' (pero realmente no quiero hacer ninguna de estas cosas). ¿Alguien tiene alguna idea sobre esto? ¿He malentendido algo aquí?

+1

Usted está al tanto de [Reactive] (http://www.reactive-web.co.cc/), ¿verdad? –

+2

Reactiva es genial, pero rompe algunas ideas en FRP. Por ejemplo, no tiene una noción de Comportamientos continuos: las señales en Reactivo cambian discretamente en el tiempo entre diferentes valores. Originalmente estaba confundido sobre cómo encaja esto en FRP y hace una pregunta: Hace un tiempo, http://stackoverflow.com/questions/7451317/is-the-signal-representation-of-functional-reactive-programming-correct – seadowg

+0

Reactive en realidad no tiene ninguna funcionalidad como 'snapshot' por lo que yo sé. – seadowg

Respuesta

3

Oh veo lo que quieres decir ahora.

Su "solo puede muestrear en la restricción 'ahora'" no es lo suficientemente ajustado, creo. Necesita ser un poco más fuerte para evitar mirar hacia el pasado. Dado que está utilizando una concepción ambiental de now, definiría las funciones de construcción del comportamiento en términos de ello (siempre que now no pueda avanzar mediante la mera ejecución de las definiciones, lo que, según mi última respuesta, sería complicado). Por ejemplo:

Stepper(i,e) es un comportamiento con el valor i en el intervalo [now,e1] (donde e1 es el tiempo de la primera ocurrencia de e después now), y el valor de la última ocurrencia de e después.

Con esta semántica, su predicción sobre el valor de stepper que se metió en este enigma se desmonta, y el paso a paso ahora tendrá el valor 0. No sé si esta semántica es deseable, pero me parece lo suficientemente natural

+0

Esta es una muy buena manera de presentarlo. Me estoy frustrando al tratar de encontrar una manera de mantener la semántica original (hermosa) sin usar una cantidad ilimitada de memoria. Me he dado cuenta de que algunas implementaciones eliminan 'stepper' y 'switcher' debido a esto, pero parecen tan poderosas. Ah bueno. – seadowg

+0

@seadowg, la semántica de Fran es excelente, pero hasta ahora no lo hemos implementado de manera eficiente (siempre tienen una fuga de espacio y una lentitud correspondiente). Personalmente gasté unos 6 meses en este problema. Tampoco podemos determinar ningún * motivo * por el que sería imposible, por lo que aún puede existir una solución. Basta decir que no será obvio. – luqui

+1

@luqui: En [esta publicación del blog] (http://apfelmus.nfshost.com/blog/2012/01/01-frp-api-0-5.html), Heinrich Apfelmus apunta a [un documento] (http : //cs.ioc.ee/~tarmo/tsem10/jeltsch-slides.pdf) que supuestamente da una explicación de por qué el tipo de cambio de evento dinámico estándar es intrínsecamente incorrecto. No soy lo suficientemente experto como para entenderlo, pero ¿has visto esto y, de ser así, no lo encuentras convincente? (Un poco fuera de tema, lo sé, pero asumí que esto sería bien conocido en la comunidad de FRP cuando lo vi). – ehird

3

Por lo que puedo decir, usted está preocupado por una condición de carrera: qué ocurre si ocurre un evento mientras se está ejecutando el código.

Al código puramente funcional no le gusta tener que saber que se ejecuta. Las técnicas funcionales están en su máxima expresión en la configuración pura, de modo que no importa en qué orden se ejecuta el código. Una forma de salir de este dilema es pretender que cada cambio ocurrió en un código imperativo (interno, probablemente) sensible; pretender que cualquier declaración funcional en el marco de FRP ocurre en 0 tiempo por lo que es imposible que algo cambie durante su declaración.

Nadie debería dormir, o realmente hacer algo sensible al tiempo, en una sección del código que es declarando comportamientos y cosas. Esencialmente, el código que funciona con objetos FRP debe ser puro, entonces no tiene ningún problema.

Esto no excluye necesariamente la ejecución en varios subprocesos, pero para admitir eso es posible que deba reorganizar sus representaciones internas.Bienvenido al mundo de la implementación de la biblioteca de FRP: sospecho que su representación interna fluctuará muchas veces durante este proceso. :-)

+0

Punto de interés. No me preocupa si algo ocurre mientras se está ejecutando este código (todo lo que puede ser un problema) pero si mouseB ocurre antes. Es simplemente que, dada la definición de 'snapshot', la 'última' ocurrencia en el evento devuelto sería (t, slider.at (t)) donde t seadowg

0

Estoy confundido acerca de su confusión. La forma en que veo es que Stepper "establecerá" el comportamiento a un nuevo valor cada vez que ocurra el evento. Por lo tanto, lo que ocurre es lo siguiente:

En el instante en que se produce el evento mouseB, el valor del comportamiento slider será leído (snapshot). Este valor se "configurará" en el comportamiento stepper.

Por lo tanto, es cierto que el Stepper "recordará" valores del pasado; el punto es que solo recuerda el último valor del pasado, no todo.

Semánticamente, lo mejor es modelar Stepper como una función que propone luqui.

+0

Sí, si no permitimos el muestreo anterior. Mi problema es que si llamamos instantánea a un comportamiento utilizando un evento que tiene ocurrencias en el pasado, estaremos muestreando este comportamiento usando un tiempo pasado (que no quiero permitir). Stepper fue utilizado para ayudar al ejemplo. – seadowg

+0

@seadowg: Ah, ya veo. Tienes dos opciones: o bien te aseguras de que en algún momento, el pasado estuvo en el presente, es decir, que ya "recorriste las últimas ocurrencias". O tiene que * recortar * las ocurrencias pasadas de las que acaba de enterarse. Estas son las únicas formas de evitar una fuga de tiempo (= recordar una cantidad ilimitada de datos del pasado). En general, la acumulación y el cambio dinámico de eventos no se pueden combinar libremente, tiene que haber algunas restricciones. –

Cuestiones relacionadas