Как я могу реализовать несколько условий if в моем коде, как показано ниже
person = %Person{}
if x.name == "Test" do
person = %{person | name: "Test"}
end
if x.age == 50 do
person = %{person | age: 50}
end
здесь «x» - это еще один объект, в котором я пытаюсь проверить данные, а затем соответствующим образом обновить структуру человека. Я уже написал код, как указано выше, но получил предупреждение ниже
the variable "person" is unsafe as it has been set inside one of: case, cond, receive, if, and, or, &&, ||. Please explicitly return the variable value instead. For example:
case integer do 1 -> atom = :one 2 -> atom = :two endshould be written as
atom = case integer do 1 -> :one 2 -> :two end





Вы не можете повторно привязать переменную внутри блока. Как предлагается в сообщении об ошибке, установите его явным образом:
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
Когда вы сопоставляете несколько предложений для проверки поля, я бы совмещал функции, проверяющие части, следующим образом:
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, чтобы вырезать ненужные поля, а затем преобразовать x в структуру с помощью функции struct(Person, x).
Все в Эликсире неизменяемо. Я бы посоветовал вам прочитать это великое произведение Хосе Валима о перепривязке переменных в Elixir.
Функциональность, которая вам нужна, в основном выглядит как уменьшение 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'}