2016-11-20 2 views
1

: Ich bin Elixier mit harter Zeit, die Variablen zu aktualisieren. Hilfe benötigen. Ich habe zwei KartenWie innen Funktion in Elixier Boolesche Variable aktualisieren

firstMsg = %{msg: "Hello", vt: %{"p1" => 1, "p2" => 1, "p3" => 1}, from: "p3"} 
state = %{ :name => "p2", 
       vector: %{"p1" => 0, "p2" => 0, "p3" => 0}, 
       participants: ["p1","p3","p2"] 
      } 

ich diese zwei Karten in einer Funktion bin vorbei, die mich entweder wahr oder falsch, je nach bestimmten Bedingungen zurückgeben sollten.

defmodule Testfunc do 
def keep_in_pending(firstMsg, state) do 
    if (firstMsg.vt[firstMsg.from] == state.vector[firstMsg.from] + 1) do 
    #IO.puts("Origin proc clock is 1 step ahead from rcvd process Origin clk") 
    checking = false #initially set this to false 
    for n <- state.participants do 
     if n != firstMsg.from do #filter the origin processes 
      IO.puts("#{n}: #{inspect firstMsg.vt[n]} <= #{n}: #{inspect state.vector[n]} ") 
      checking = cond do 
      (firstMsg.vt[n] <= state.vector[n]) -> false 
      (firstMsg.vt[n] > state.vector[n]) -> true 
      end 
     end 
     end 

    end 
    checking 
end 
end 

out = Testfunc.keep_in_pending(firstMsg, state) 
IO.puts("#{inspect out}") 

Es gibt mir immer falsch (Wert, den ich ursprünglich zugewiesen), und aktualisiert nicht. Ich denke, der Umfang der Variablen beschränkt sich auf das innere "Wenn". Kann jemand mir einen Vorschlag geben, wie ich diesen Code so anordnen kann, dass er mir den richtigen aktualisierten booleschen Wert zurückgibt?

Also in diesem Fall sollte es zurückgeben mich wahr, weil firstMsg.vt [ "p1"]> state.vector [ "p1"].

Antwort

2

Also hier ist eine Idee: Wenn Sie eine Funktion zurückgeben boolean versuchen zu machen, es ist nur eine boolean zurückgeben machen, ordnet es nicht zu einer Variablen. Bei der Zuweisung von if/case/cond wird eine Warnung angezeigt. Außerdem weisen Sie die checking nicht neu zu, da Variablen, die innerhalb des Verständnisses (for) gebunden sind, auf diesen Bereich beschränkt sind. Ihre besten Werkzeuge in Elixir werden der erste Mustervergleich sein und der Pipe-Operator, also versuchen Sie immer, sie zu verwenden.

Hier ist eine Idee, dass Code Refactoring:

defmodule Testfunc do 
    def keep_in_pending(firstMsg, state) do 
    if (firstMsg.vt[firstMsg.from] == state.vector[firstMsg.from] + 1) do 
     state.participants 
     |> Enum.filter(fn (n) -> n != firstMsg.from end) 
     |> Enum.reduce(fn (n, _) -> 
     cond do 
      (firstMsg.vt[n] <= state.vector[n]) -> false 
      (firstMsg.vt[n] > state.vector[n]) -> true 
     end 
     end) 
    end 
    end 
end 
+0

Aber es bringt mich immer in allen Fällen falsch zurück. –

+0

Seltsam, ich werde "wahr", mit allen Informationen, die Sie gaben. –

4

Willkommen bei Elixir. Du hast recht, es ist eine Frage des Umfangs, aber es läuft ein bisschen tiefer. Elixier ist eine Sprache, in der deine Daten unveränderlich sind. Sie können checked nicht auf false setzen, eine Schleife ausführen und sie irgendwo in dieser Schleife auf true setzen. Das würde checked mutieren. Es ist nicht so, dass jemand teuflische Scope-Regeln entworfen hat, um dies zu verhindern, sondern dass die zugrunde liegende virtuelle Maschine den Status nicht mutiert.

Die Art der Programmierung, wo Sie einigen Zustand gesetzt, dann eine Prozedur ausführen, die diesen Zustand ändert, beruhen auf veränderbaren Zustand. Wenn der Status unveränderlich ist, ist die Alternative zu einer Schleife stattdessen Rekursion. Sie tragen bei jedem rekursiven Aufruf einen neuen Status.

Sie lernen eine funktionale Sprache, und ich denke, es wird hilfreich sein, Ihren Code in ein paar Funktionen auseinander zu ziehen. Dies wird sowohl Ihre unmittelbaren Bedenken adressieren als auch Ihren Code verständlicher machen.

def keep_in_pending(%{from: from, vt: vt}, %{vector: vector, participants: ps}) do 
    if vt[from] == vector[from] + 1 do 
    ps 
    |> Enum.reject(& &1 == from) 
    |> check_participants(vector, vt, false) 
    end 
end 

def check_participants([], _, _, bool), do: bool 
def check_participants([h | t], vector, vt, bool) do 
    check_participants(t, vector, vt, vt[h] > vector[h]) 
end 

Ich werde es kurz erklären.

Beachten Sie zuerst, dass ich Muster den Eingängen angepasst habe, um die interessanten Teile, die wir im Funktionskörper verwenden, herauszuholen. Dies wird einige der repetitiven firstMsg.from Geschäft los. (Btw, snake_case Ihre Variablennamen.)

Zweitens habe ich die gnarly äußere Wenn-Bedingung nicht berührt. Ich weiß einfach nicht, was es bedeutet. Sie sollten es vielleicht extrahieren und ihm eine Absicht geben, die Namen offenbart.

Die echte Aktion beginnt, wenn wir Teilnehmer pipes. Sie haben in Ihrem Listenverständnis gefiltert. Ich habe stattdessen mit Enum.reject/1 gefiltert. Dann leiten wir die Liste in eine rekursive Funktion. Es wird den booleschen Wert bis zum Ende durchgehen, beginnend mit false. Es muss Werte in vt und vector überprüfen, so dass sie auch übergeben werden.

Die erste Regel der Rekursion ist die erste Regel der Rekursion. Nein, warte. Es ist zu überlegen, wie die Rekursion beendet werden soll. Wir arbeiten eine Liste der Teilnehmer durch, damit wir aufhören, wenn die Liste leer ist. An diesem Punkt haben wir den booleschen Wert, nach dem wir suchen, also gib ihn einfach zurück.

Der rekursive Schritt ist ein Element aus der Liste (h), verwendet, um einen neuen Pick-off boolean (vt[h] > vector[h]) zu ermitteln und um die Funktion wieder mit dem Rest der Liste (check_participants(t, ...)) nennen.

Hoffe, das hilft! Viel Spaß beim Lernen der funktionalen Programmierung!

+0

Schön erklärt ... :) –

Verwandte Themen