Несколько, если условие в эликсире - PullRequest
0 голосов
/ 29 мая 2018

Как я могу реализовать несколько, если условия в моем коде, как показано ниже

person = %Person{}

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

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

здесь "x" - это другой объект, в котором я пытаюсь проверить данные и затем соответствующим образом обновить структуру лица.Я уже написал код, как указано выше, но получил следующее предупреждение

, переменная "персона" небезопасна, так как она была установлена ​​внутри одного из: case, cond, receive, if и, или, или & &&,||.Пожалуйста, явно верните значение переменной.Например:

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

должно быть записано как

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

Ответы [ 3 ]

0 голосов
/ 30 мая 2018

Когда вы сопоставляете несколько предложений для проверки поля, я бы комбинировал функции, которые проверяют части, следующим образом:

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).

0 голосов
/ 30 мая 2018

Все в Эликсире является неизменным.Я бы посоветовал вам прочитать это замечательное письмо Хосе Валима о связывании переменных в 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'}
0 голосов
/ 30 мая 2018

Вы не можете перепривязать переменную внутри блока.Как следует из сообщения об ошибке, установите его в явном виде:

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
...