Shortcourcing von Futures in clojure

8

Ich habe zwei Futures, die sich in booleans auflösen. Ich möchte im Grunde so etwas wie

machen %Vor%

Aber mit der Optimierung, die zuerst abgeschlossen wird, wenn es wahr ist, warte ich nicht auf das Ende der verbleibenden Zukunft; geh einfach. Wenn der Wert falsch ist, warten Sie natürlich, bis die verbleibende Zukunft beendet ist. Gibt es einen einfachen Weg, dies zu tun?

    
Dax Fohl 01.06.2013, 01:43
quelle

4 Antworten

4

Im allgemeinen Fall können Sie den beiden Zustellern das gleiche Versprechen geben. Zum Beispiel:

%Vor%

Der Aufruf von (foo) liefert zufällig :a oder :b , sobald der erste deliver auftritt; das andere deliver wird ein No-Op sein.

Für Ihren speziellen Fall müssen zwei Boolesche Werte zurückgegeben werden. Das einzige, was ich mir vorstellen kann (und es ist ein bisschen unordentlich), wäre ein drittes Versprechen, das zwischen den Zustellern geteilt wird:

%Vor%
  • Wenn a zuerst true liefert, wird or sofort beendet.
  • Wenn a zuerst false liefert, gibt @a sofort zurück und blockt dann auf @b .
  • Wenn b zuerst true liefert, wird or sofort beendet.
  • Wenn a zuerst false liefert, blockiert es auf @a .

Wiederholt (foo) aufrufen und Sie sollten die erwarteten Ergebnisse sehen, insbesondere wenn :or ist true , dann manchmal :a? oder :b? wird false , aber beide werden immer true if :or ist false .

    
Alex Taggart 01.06.2013 02:08
quelle
3

Dies ist jetzt möglich mit core.async , wie in meiner Antwort auf die neue mit Clojure threading lang laufenden Prozesse und vergleichen ihre Rückkehr Frage. Diese Antwort definiert thread-and ; Diese Frage erfordert thread-or :

%Vor%

Test mit (ständig falsch) und (immer wahr):

%Vor%

Beachten Sie auch, dass ein Kurzschluss tatsächlich funktioniert:

%Vor%     
Michał Marczyk 12.07.2013 21:47
quelle
1

Ich liebe diese Frage absolut. Vielleicht bin ich überrascht, eine neue Frage zu sehen, die so einfach ist. Wie auch immer, beiseite sabbernd denke ich Ich habe etwas, das für dich arbeiten würde.

Anstatt zu tun:

%Vor%

Mach:

%Vor%

Der Trick ist zu testen, ob etwas realisiert wird, bevor gefragt wird, ob es true oder false ist.

Dies könnte wie folgt auf ein Makro verallgemeinert werden:

%Vor%

Und dann benutzt wie:

%Vor%

Warte eine Sekunde. Vielleicht verstehe ich dein Problem falsch. Vielleicht möchten Sie die Ausführung blockieren, bis EINER der Futures abgeschlossen ist und true zurückgibt. In diesem Fall tun Sie die then-Klausel Ihrer if , ODER beide Ihrer Futures sind fertig und geben weder true , in denen Falls du die else-Klausel von if machst. Das ist eine andere Geschichte.

Der erfolgreichste Weg, den ich mir vorstellen kann, ist nicht gerade hübsch, aber auch nicht schrecklich lang:

%Vor%

Nun wird loop verwendet, um wiederholt zu loopen, bis eines von zwei Dingen eintritt: Entweder einer der Futures ist sowohl realisiert als auch true , in welchem ​​Fall die Schleife mit true zurückkehrt; oder alle Futures werden realisiert und alle von ihnen false , in welchem ​​Fall die Schleife mit false zurückkehrt. Es ist wichtig, die (not ...) -Ausdrücke am Ende des übergeordneten (and ...) -Ausdrucks zu haben, damit Sie nicht bei der Überprüfung, ob irgendwelche Futures true oder false sind, stecken bleiben, bis sie alle realisiert sind.

Diese neue Lösung könnte verallgemeinert werden als:

%Vor%

Und genauso verwendet wie das obige future-or Beispiel.

Jetzt weiß ich fast nichts über Optimierung. Aber soweit ich das beurteilen kann, ist dies sicherlich nicht so effizient, wie es theoretisch sein könnte, denn sobald eine gegebene Zukunft realisiert ist, besteht keine wirkliche Notwendigkeit, ihren Wert mehr als einmal zu testen. Nun, hier sind zwei Lösungen, die ich mit future-some betitelt habe. Da sich die zu testenden Futures nach jeder Schleifen-Iteration möglicherweise dynamisch ändern müssen, musste ich sie zu einer Funktion machen. Auf diese Weise ist diese neue Methode analog zu some , nicht or . In Naturalien habe ich das Verhalten geändert, um eine Sammlung von Futures zu nehmen (im Gegensatz zu einer variablen Anzahl von einzelnen Argumenten - ein weiterer Unterschied zwischen some und or ). Eine Lösung überprüft nicht (denke ich):

%Vor%

Hier gibt es eine Menge Details, aber das Wesentliche ist Folgendes: Wenn es keine zu testenden Futures gibt, gibt es false zurück, ansonsten iteriert es die Liste der Futures und testet, ob irgendwelche von ihnen realisiert werden. Wenn eine Zukunft realisiert wird, und auch Dereferenzierungen in true , bricht die Iteration ab, um true zurückzugeben. Wenn eine Zukunft realisiert wird, aber nicht auf true dereferenziert wird, wird die Iteration mit dem nächsten Element fortgesetzt. Wenn eine Zukunft nicht realisiert ist, wird eine Liste hinzugefügt, die bei der nächsten Rekursion von future-some verwendet wird.

Und die andere Lösung ist prägnanter, aber etwas weniger optimal:

%Vor%

Ähnlich wie das andere, außer dass es zuerst das realisierte herausfiltert, dann testet und dann erneut filtert (dieses Mal invers - um das unrealisierte zu erhalten), wenn es wiederholt werden muss. Diese zweite Filterung ist der ineffiziente Schritt.

Ein Problem mit allen von mir vorgeschlagenen Lösungen ist, dass zukünftige Stornierungen zu Fehlern bei der Dereferenzierung führen würden, wenn sie wahrscheinlich einfach so weitergehen sollten, als ob diese Zukunft falsch wäre. Dies ist lösbar, indem (not (future-cancelled? ...)) -Ausdrücke vor jedem Dereferenzieren in jeden einzelnen (and ...) -Ausdruck gesetzt werden. Oder, für die Funktionen future-some , müssten Sie das Prädikat realized? durch (some-fn (comp not future-cancelled?) realized?) oder #(and (not (future-cancelled %)) (realized? %)) für schwache Nerven ersetzen.

Nochmals, ernsthaft, danke für diese Frage.

    
Omri Bernstein 02.06.2013 07:30
quelle
0

Wenn man davon ausgeht, dass man die Futures nicht alle X millis abfragen will und die Erstellung der futures / threads oder fn, die sie ausführen, nicht kontrollieren kann, besteht die Lösung darin, noch mehr Threads zu erstellen, wobei jeder Thread wartet für eine Zukunft:

%Vor%     
DanLebrero 15.06.2013 01:21
quelle