问题描述
我在 Elixir 应用中有以下功能:
def emojify(%Conv{status: 200,resp_headers: resp_headers} = conv) do
body = if resp_headers["Content-Type"] == "application/json",do: conv.resp_body,else: "?" <> "\n\n" <> conv.resp_body <> "\n\n" <> "?"
%{ conv | resp_body: body }
end
def emojify(%Conv{} = conv),do: conv
我想重构它以消除其中对 if
的需要。我想这样做的方法是通过模式匹配 resp_headers
内的内容类型,但这将是地图内地图的模式匹配(地图内的结构更精确,但我不不认为这个细节在这种情况下是相关的),我不知道该怎么做。
我正在尝试类似 def emojify(%Conv{status: 200,resp_headers: %{"Content-Type" => "application/json"}} = conv)
的东西,但我知道这只有在 resp_headers
内部只有 "Content-Type" => "application/json"
时才有效,但事实并非如此。那么我如何才能做到这一点?
解决方法
我知道这只有在 resp_headers 里面只有 "Content-Type" => "application/json"
时才有效
这个假设是错误的。如果匹配中的字段出现在输入并且所有固定变量都匹配,则映射匹配。你没有固定变量,所以你没问题。
匹配空地图经常被用来代替is_map(map)
守卫作为foo(%{} = map) do ...
%{} = %{foo: 42,bar: :baz} # success
# and also
%{foo: foo} = %{foo: 42,bar: :baz} # success
foo
#⇒ 42
也就是说,答案是
def emojify(%Conv{
status: 200,resp_headers: %{"Content-Type" => "application/json"}} = conv),do: %{ conv | resp_body: conv.resp_body }
def emojify(%Conv{status: 200} = conv),do: %{ conv | resp_body: "?" <> "\n\n" <> conv.resp_body <> "\n\n" <> "?"}
def emojify(%Conv{} = conv),do: conv
旁注:带有固定变量的示例。
%{foo: 42} = %{foo: 42,bar: :baz} # success
foo = 42
%{foo: ^foo} = %{foo: 42,bar: :baz} # success
%{foo: ^foo} = %{foo: :incorrect,bar: :baz} # raises
,
你可以像这样进行模式匹配
cat (max)score fruit_color
cat
a a 99.0 apple_yellow
b b 9.0 apple_green
c NaN NaN NaN
d NaN NaN NaN
e NaN NaN NaN
f NaN NaN NaN
['none','red','yellow','green']
您始终可以对映射或结构中特定键的值进行模式匹配
有关更多信息,请查看 joyofelixir。