Dat*_*sik 2 functional-programming elixir
我最近开始学习Elixir,我真的非常喜欢它,但它是我用过的第一种函数式编程语言.我遇到的问题来自于我一直在阅读教程和在LearnElixir上观看截屏视频,你应该尽量避免使用IF类型语句.
但我发现自己经常筑巢cond或case
我会用Golang或Javascript之类的其他语言解决这些解决方案,只需使用带有早期返回的if语句,这样超出该范围的代码就不会运行,这使得我不得不通过检查falsy来占用条件的99%的时间价值观和回归.
因此,在Elixir(或其他函数式编程语言)中,如何在不使用嵌套的情况下以适当的方式编写类似下面的内容,并利用该语言的功能.
def loginPost(conn, %{"user" => user_params}) do
# Look for user in database
query = from u in User,
where: u.email == ^user_params["email"],
select: [u.email, u.username, u.password]
data = Repo.all(query)
# Check to see if a user had been found
case (length data) == 0 do
true -> # No user was found, send an error message
conn
|> json(%{ success: false, errors: ["Wrong username or password"]})
false -> # A user was found, compare password
[[email, username, db_password]] = data
case Comeonin.Bcrypt.checkpw(user_params["password"], db_password) do
true -> # Password was correct, set session and return a json response
conn
|> put_session(:authenticated, true)
|> put_session(:username, username)
|> put_session(:email, email)
|> json(%{success: true}) # Send json response and redirect on client side
false -> # Password was incorrect, send an error message
conn
|> json(%{success: false, errors: ["Wrong username or password"]})
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
一种方法是使用with.您可以创建单独的函数,如下所示:
def authenticate(email, password) do
with {:ok, user} <- find_user(email),
{:ok, user} <- validate_password(user, password),
{:ok, user} <- validate_preconditions(user)
do: {:ok, user}
end
defp find_user(email) do
# return {:ok, user} if user is found, return {:error, :user_not_found} otherwise
end
defp validate_password(user, password) do
# return {:ok, user} if password is correct, return {:error, :invalid_password} otherwise
end
defp validate_preconditions(user) do
# return {:ok, user} if user is not banned or whatever, return {:error, :cant_be_logged_in} otherwise
end
Run Code Online (Sandbox Code Playgroud)
然后你可以在你的控制器功能中使用它,如下所示:
def loginPost(conn, %{"user" => user_params}) do
case authenticate(user_params["email"], user_params["password"]) do
{:ok, user} -> # start session
{:error, error_type} -> # handle error
end
end
Run Code Online (Sandbox Code Playgroud)
这个例子可能会更好,但你明白了.
你也可以从这个问题中读出答案