implementación de una máquina de estados usando la palabra clave" yield"


Es factible usar la palabra clave yield para implementar una máquina de estados simple como se muestra aquí. Para mí, parece que el compilador de C# ha hecho el trabajo duro para usted, ya que implementa internamente una máquina de estados para hacer que la declaración de rendimiento funcione.

¿Puede poner en marcha el trabajo que el compilador ya está haciendo y hacer que implemente la mayor parte de la máquina de estados por usted?

Alguien Ha hecho esto, es técnicamente posible?

Author: Matt Warren, 2009-07-28

4 answers

Es factible, pero es una mala idea. Los bloques de iteradores se crearon para ayudarlo a escribir iteradores personalizados para colecciones, no para resolver el problema de propósito general de implementar máquinas de estado.

Si desea escribir una máquina de estados, simplemente escriba una máquina de estados. No es difícil. Si desea escribir muchas máquinas de estado, escriba una biblioteca de métodos auxiliares útiles que le permitan representar máquinas de estado de forma limpia y, a continuación, utilice su biblioteca. Pero no abuse de una construcción de lenguaje pensado para algo completamente diferente que solo pasa a usar máquinas de estado como detalle de implementación. Eso hace que su código de máquina de estado sea difícil de leer, comprender, depurar, mantener y extender.

(Y por cierto, hice una doble toma al leer tu nombre. Uno de los diseñadores de C# también se llama Matt Warren!)

 45
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-28 16:23:14

Sí, es absolutamente posible y fácil de hacer. Puede disfrutar usando construcciones de flujo de control(for, foreach, while, ... goto (usar goto se adapta particularmente a este escenario ;))) junto con yield s para construir uno.

IEnumerator<State> StateMachine
             (Func<int> currentInput /* gets current input from IO port */, 
              Func<int> currentOutput) {
    for (;;)  {
       if ((currentInput() & 1) == 0) 
           yield return new State("Ready"); 
       else {
           if (...) {
               yield return new State("Expecting more data");
               SendOutput(currentOutput());
               while ((currentInput() & 2) != 0) // while device busy
                    yield return new State("Busy");
           else if (...) { ... } 
       }
    }
}

// consumer:
int data;
var fsm = StateMachine(ReadFromIOPort, () => data);
// ...
while (fsm.Current != "Expecting more data")
    fsm.MoveNext();
data = 100;
fsm.MoveNext();
 7
Author: Mehrdad Afshari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-28 15:49:30

Si bien esto no es una máquina de estados en el sentido clásico, el artículo sobre Micro Threading basado en Iteradores utiliza yield creativamente para acciones basadas en estados.

IEnumerable Patrol ()
{
    while (alive){
        if (CanSeeTarget ()) {
            yield return Attack ();
        } else if (InReloadStation){
            Signal signal = AnimateReload ();
            yield return signal;
        } else {
            MoveTowardsNextWayPoint ();
            yield return TimeSpan.FromSeconds (1);
        };
    }
    yield break;
}
 4
Author: Michael Stum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-08 00:14:53

Los bloques iteradores efectivamente implementan máquinas de estado, pero la parte difícil es obtener la siguiente entrada. ¿Cómo vas a saber a dónde seguir? Supongo que podrías tener algún tipo de variable compartida de "transición actual", pero eso es algo asqueroso.

Si no necesitas ninguna entrada (por ejemplo, tu máquina de estados está simplemente alternando entre estados) entonces es fácil, pero ese no es el tipo interesante:)

¿Puede describir el tipo de máquina de estado que le interesa?

 3
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-28 15:24:14