Anu*_*raz 1 variables recursion scope functional-programming elixir
我是Elixir的新手,很难更新变量。需要一些帮助。我有两张地图
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"]
}
Run Code Online (Sandbox Code Playgroud)
我在函数中传递了这两个映射,根据某些条件,该函数应该返回true或false。
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}")
Run Code Online (Sandbox Code Playgroud)
它总是给我假(我最初分配给它的值),并且不会更新。我认为变量的范围仅限于内部的“ if”。谁能给我关于如何重新安排此代码的建议,以便它返回正确的更新后的布尔值?
因此,在这种情况下,它应该返回true,因为firstMsg.vt [“ p1”]> state.vector [“ p1”]。
欢迎来到Elixir。没错,这是范围的问题,但它的作用要深得多。Elixir是一种数据不可变的语言。您不能将其设置checked为false,运行循环,并将其设置为true。那会变checked。不是有人设计了恶魔般的范围规则来防止这种情况,而是底层虚拟机不会改变状态。
设置某种状态然后运行更改该状态的过程的编程风格取决于可变状态。当状态是不可变的时,循环的替代方法是递归。您在每个递归调用中都带有新状态。
您正在学习一种功能语言,我认为将您的代码分解为几个功能会有所帮助。这既可以解决您的紧迫问题,又可以使您的代码更易于理解。
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
Run Code Online (Sandbox Code Playgroud)
我将简要说明。
首先,请注意,我已经对输入进行了模式匹配,以提取我们在函数主体中使用的有趣部分。这摆脱了一些重复的firstMsg.from业务。(顺便说一句,snake_case您的变量名。)
其次,我还没有触及过时的if条件。我根本不知道这意味着什么。您也许应该提取它,并给它一个意图揭示名称。
真正的行动始于我们吸引参与者的时候。您正在对列表理解进行过滤。我已经过滤了Enum.reject/1。然后,将列表通过管道传递到递归函数中。以开头的布尔值将一直执行到最后false。它需要检查值vt和vector,因此他们也过去了。
递归的第一条规则是递归的第一条规则。不,等等 在考虑如何终止递归。我们正在处理参与者列表,因此当列表为空时我们将停止。到那时,我们拥有了要查找的布尔值,因此只需将其返回即可。
递归步骤是从列表(h)中选择一个项目,使用它来确定新的布尔值(vt[h] > vector[h]),然后使用列表的其余部分再次调用该函数(check_participants(t, ...))。
希望这可以帮助!玩得开心学习功能编程!