elixir中的多个if条件

时间:2018-05-29 20:30:35

标签: elixir

如何在我的代码中实现多个if条件,如下所示

person = %Person{}

if x.name == "Test" do 
  person = %{person | name: "Test"}
end

if x.age == 50 do 
 person = %{person | age: 50}
end

这里“x”是我尝试验证数据然后相应地更新person结构的另一个对象。 我已经编写了上面的代码,但得到了以下警告

  

变量“person”不安全,因为它已被设置在以下之一:   case,cond,receive,if,and,or,&&,||。请明确退回   变量值而不是。例如:

case integer do
  1 -> atom = :one
  2 -> atom = :two
end
     

应该写成

atom =
  case integer do
    1 -> :one
    2 -> :two
  end

3 个答案:

答案 0 :(得分:3)

当您匹配多个子句来验证字段时,我会组合验证这些片段的函数,如下所示:

defmodule PersonChecker do
  def validate(x, person) do
    person
    |> validate_name(x)
    |> validate_age(x)
  end

  defp validate_name(person, %{name: name}) when name == "Test" do
    %{person | name: "Test"}
  end
  defp validate_name(person, _x), do: person

  defp validate_age(person, %{age: age}) when age == 50 do
    %{person | age: 50}
  end
  defp validate_age(_x, person), do: person
end

如果您想使用case而不是多个validate_name函数,它将如下所示:

defp validate_name(person, x) do
  case x.name do
    "Test" -> %{person | name: "Test"}
    _ -> person
  end
end

顺便说一句,根据您的使用情况,使用x删除您不想要的字段可能会更容易,然后使用xstruct(Person, x)转换为结构<ns1:ATT_ADDR_VAL_REQ xmlns="http://lsr.att.com/preorder"> <ns2:ADDR_VAL_REQ xmlns="http://lsr.att.com/obf/tML/UOM"> 函数。

答案 1 :(得分:2)

您无法重新绑定块内的变量。如错误消息所示,请将其设置为显式:

person = %Person{}
person = if x.name == "Test", do: %{person | name: "Test"}, else: person
person = if x.age == 50, do: %{person | age: 50}, else: person

即使变量是不可变的,Elixir也允许重新绑定,但是如果不允许它会更容易理解(比如在Erlang中)。在这种情况下,您必须编写如下内容:

person = %Person{}
person_with_name = if x.name == "Test", do: %{person | name: "Test"}, else: person
person_with_name_and_age = if x.age == 50, do: %{person_with_name | age: 50}, else: person_with_name

答案 2 :(得分:2)

Elixir中的所有东西都是不可改变的。我建议你阅读Elixir中重新绑定变量的this great writing by José Valim

您所使用的功能主要是减少字段列表中的struct,这就是为什么我可能会选择Enum.reduce/3

defmodule Person, do: defstruct ~w|foo name age|a
x = [name: true, age: false] # flags

~w|name age|a
|> Enum.zip(['Test', 50])
|> Enum.reduce(%Person{foo: :bar}, fn {field, value}, acc ->
     if x[field], do: %{acc | field => value}, else: acc
   end)
#⇒ %Person{age: nil, foo: :bar, name: 'Test'}