2010-08-29 12 views
16

Im Moment versuche ich Functional Programming in Scala zu verstehen und bin auf ein Problem gestoßen, das ich selbst nicht herausfinden kann.Korrekte Verwendung von veränderbaren/unveränderlichen Listen

sich folgende Situation vor:

Sie haben zwei Klassen: -Controller und Bot. Ein Bot ist ein unabhängiger Aktor, der von einem Controller initiiert wird, einen teuren Vorgang ausführt und das Ergebnis an den Controller zurückgibt. Der Zweck der Controller ist daher einfach zu beschreiben: Instanziieren Sie mehrere Objekte Bot, starten Sie sie und erhalten Sie das Ergebnis.

So weit, so gut; Ich kann das alles implementieren, ohne veränderbare Objekte zu verwenden.

Aber was soll ich tun, wenn ich das Ergebnis speichern haben, dass ein Bot kehrt, es für einen anderen Bot später als Eingabe verwendet werden (und später bedeutet, auf dass Ich weiß nicht, wenn bei Kompilierzeit!)?

Dies mit einer veränderbaren Liste oder Sammlung zu tun ist ziemlich einfach, aber ich füge meinem Code viele Probleme hinzu (da es sich hier um Nebenläufigkeit handelt).

Ist es möglich, nach dem FP-Paradigma, dies zu lösen, indem Sie unveränderliche Objekte (Listen ...) sicher verwenden?

BTW, im neuen zu FP, so dass diese Frage könnte dumm klingen, aber ich kann nicht herausfinden, wie diese :) zu lösen in der Regel

Antwort

6

Dies ist, wie ein Erlang-wie Schauspieler in Scala aussehen könnten:

case class Actor[State](val s: State)(body: State => Option[State]) { // immutable 
    @tailrec 
    def loop(s1: State) { 
    body(s1) match { 
     case Some(s2) => loop(s2) 
     case None =>() 
    } 
    } 

    def act = loop(s) 
} 

def Bot(controller: Actor) = Actor(controller) { 
    s => 
    val res = // do the calculations 
    controller ! (this, res) 
    None // finish work 
} 

val Controller = Actor(Map[Bot, ResultType]()) {s => 
    // start bots, perhaps using results already stored in s 
    if ( 
    // time to stop, e.g. all bots already finished 
) 
    None 
    else 
    receive { 
     case (bot, res) => Some(s + (bot -> res)) // a bot has reported result 
    } 
} 

Controller.act 
+0

Danke für diese Antwort. Ich habe mit deinem Beispiel herumgespielt und es an meine Bedürfnisse angepasst, und es scheint die perfekte Lösung für mein spezifisches Problem zu sein! –

7

Schauspieler internen Zustand haben, sein, sich selbst, wandelbar Tiere. Beachten Sie, dass Schauspieler keine FP-Sache sind.

Das von Ihnen beschriebene Setup scheint sich auf einen veränderbaren Controller zu verlassen, und es ist schwierig, es in einer Sprache zu umgehen, die standardmäßig nicht nicht streng ist. Je nachdem, was Sie tun, können Sie sich auf Futures verlassen. Zum Beispiel:

case Msg(info) => 
    val v1 = new Bot !! Fn1(info) 
    val v2 = new Bot !! Fn2(info) 
    val v3 = new Bot !! Fn3(info) 
    val v4 = new Bot !! Fn4(v1(), v2(), v3()) 
    reply(v4()) 

In dieser Fall - weil !! gibt ein Future-v1, v2 und v3 werden parallel berechnet werden. Die Nachricht Fn4 empfängt als Parameter die angewendeten Futures, was bedeutet, dass gewartet wird, bis alle Werte berechnet sind, bevor die Berechnung beginnt.

Ebenso wird die Antwort nur gesendet, nachdem v4 berechnet wurde, da auch die Zukunft beantragt wurde.

Eine wirklich funktionale Art, diese Dinge zu tun, ist die funktionale reaktive Programmierung, oder kurz FRP. Es ist ein anderes Modell als Schauspieler.

Die Schönheit von Scala ist jedoch, dass Sie solche Paradigmen in dem Maße kombinieren können, dass es besser zu Ihrem Problem passt.

+0

Dank vor allem der „Zukunft“ Sache ist neu für mich und ich werde darum kümmern, obwohl ich, dass es vielleicht denken nicht wirklich helfen mir .. Aber, ich werde zuerst einen Blick in FRP werfen, die die Antwort auf alle meine Probleme sein kann (da ich FP, nicht die Verwendung von Schauspielern lernen will :)) –

+0

"und es ist schwierig zu umgehen Sie es in einer Sprache, die standardmäßig nicht nicht strikt ist. "Sie können einfach tun, was Erlang macht: Übergeben Sie den Zustand als Parameter an eine tail-rekursive Funktion. –

+0

@Alexey Ich bin mir nicht sicher, wie das genau funktionieren würde. Warum nicht eine Antwort mit einem Beispiel geben? –

Verwandte Themen