2015-11-11 8 views
8

Ich versuche herauszufinden, wie Sie eine Funktion über einen Kanal senden, und wie Sie zusätzliches Klonen vermeiden, um die Funktion am anderen Ende auszuführen. Wenn ich die zusätzlichen Klonvorgang innerhalb des Verschlusses entfernen, bekomme ich folgende Fehlermeldung:Kann nicht aus gefangenen äußeren Variablen in einem 'Fn'-Schließung bewegen

error: cannot move out of captured outer variable in an 'Fn' closure 

die Tatsache ignorieren, dass dieser Code tut absolut nichts, und macht Gebrauch von einem globalen wandelbar statischen Sender<T>, stellt es das, was ich bin versuchen zu erreichen, während die richtigen Compilerfehler geben. Dieser Code ist nicht zum Ausführen, gerade kompiliert.

Gibt es eine bessere Methode, um diesen Fehler zu umgehen und/oder eine andere Möglichkeit, Funktionen über Kanäle zu senden?

Antwort

11

Das Problem mit Fn() ist, dass Sie es mehrmals aufrufen können. Wenn Sie einen erfassten Wert verlassen, ist dieser Wert beim nächsten Aufruf nicht mehr verfügbar. Sie benötigen eine FnOnce(), um sicherzustellen, dass der Aufruf der Schließung auch ausgeht, so ist es weg und kann nicht erneut aufgerufen werden.

Es gibt keine Möglichkeit, eine Arc<Mutex<(FnOnce() + Send + Sync + 'static)>> zu haben. Dies würde wiederum erfordern, dass Sie statisch garantieren, dass, nachdem Sie die Funktion aufgerufen haben, niemand anders sie erneut aufrufen kann. Was Sie nicht können, da jemand anderes eine andere Arc auf Ihre FnOnce zeigen könnte. Was Sie tun können, ist es boxen und senden Sie es als Box<FnOnce() + Send + Sync + 'static>. Es gibt nur einen Besitzer eines Box.

Das Problem mit FnOnce() ist, ist, dass man nicht wirklich so nennen kann, während es in der Box ist, denn das erfordern würde es aus dem Box bewegt und es ruft. Aber wir wissen nicht, wie groß es ist, also können wir es nicht aus der Box herausziehen. Zukünftig könnten Box<FnOnce()> Verschlüsse direkt nutzbar werden.

"Zum Glück" dieses Problem trat häufiger auf, so gibt es FnBox. Leider erfordert dies jede Nacht zur Arbeit. Auch konnte ich nicht herausfinden, wie man die Funktionsaufrufsyntax benutzt, die in den Dokumenten beschrieben wird, aber Sie können call_box auf dem Box<FnBox()> manuell aufrufen. Versuchen Sie es in der Playground

+0

Leider ist stabil meine einzige Option. Es sieht so aus, als hättest du gerade bestätigt, was ich bereits versucht und herausgefunden habe, aber jemand anderes könnte das als super hilfreich empfinden, der die Fähigkeit hat, jeden Abend zu benutzen. Danke :) – nathansizemore

+1

Sie können einen Hack verwenden. Verwenden Sie immer noch eine 'Fn' und bewegen Sie nur in' Option', die Sie mit 'take' verlassen. Dann bekommst du einen Laufzeitfehler, wenn du deine 'Fn' falsch verwendest. –

+0

Was ist, wenn ich wegen einer Bibliotheksanforderung ein' Fn' benötige? –

Verwandte Themen