Вот самый простой подход, который я нашел, не прибегая к анонимным функциям и сложному коду.
Ваши методы, которые вы собираетесь объединить в цепочку и выйти из них, должны иметь особую арность, которая принимает кортеж {:error, _}
. Предположим, у вас есть функции, возвращающие кортеж из {:ok, _}
или {:error, _}
.
# This needs to happen first
def find(username) do
# Some validation logic here
{:ok, account}
end
# This needs to happen second
def validate(account, params) do
# Some database logic here
{:ok, children}
end
# This happens last
def upsert(account, params) do
# Some account logic here
{:ok, account}
end
На данный момент ни одна из ваших функций не связана друг с другом. Если вы правильно разделили всю свою логику, вы можете добавить арность к каждой из этих функций, чтобы распространять ошибки в стеке вызовов, если что-то пойдет не так.
def find(piped, username) do
case piped do
{:error, _} -> piped
_ -> find(username)
end
end
# repeat for your other two functions
Теперь все ваши функции будут правильно распространять свои ошибки по стеку вызовов, и вы можете передавать их в вызывающую программу, не беспокоясь о том, передают ли они недопустимое состояние следующему методу.
put "/" do
result = find(username)
|> validate(conn.params)
|> upsert(conn.params)
case result do
{:error, message} -> send_resp(conn, 400, message)
{:ok, _} -> send_resp(conn, 200, "")
end
end
Хотя вы можете в конечном итоге создать дополнительный код для каждой из ваших функций, его очень легко читать, и вы можете передавать большинство из них взаимозаменяемо, как если бы вы делали это с решением анонимной функции. К сожалению, вы не сможете передавать данные через них из канала без некоторых изменений в работе ваших функций. Всего два цента. Удачи.
person
dimiguel
schedule
07.12.2015