与地图内的地图进行模式匹配(Elixir)
Pattern matching with a map inside a map (Elixir)
我在 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"
的情况下才有效,但事实并非如此。那么我怎样才能做到这一点?
I understand that this would only work if resp_headers has only "Content-Type" => "application/json"
inside it
这个假设是错误的。如果匹配中的字段出现在输入 和 中,则地图匹配,所有固定变量都匹配。你没有固定变量,所以你没问题。
经常使用匹配到空映射而不是 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
你可以像这样进行模式匹配
def emojify( %{status: 200, resp_headers: %{"Content-Type" => "application/json" } } = conv
) do
%{ conv | resp_body: conv.resp_body }
end
def emojify(%{status: 200} = conv) do
%{ conv | resp_body: "" <> "\n\n" <> conv.resp_body <> "\n\n" <> "" }
end
def emojify(conv), do: conv
您始终可以对映射或结构中特定键的值进行模式匹配
有关更多信息,请查看 joyofelixir。
我在 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"
的情况下才有效,但事实并非如此。那么我怎样才能做到这一点?
I understand that this would only work if resp_headers has only
"Content-Type" => "application/json"
inside it
这个假设是错误的。如果匹配中的字段出现在输入 和 中,则地图匹配,所有固定变量都匹配。你没有固定变量,所以你没问题。
经常使用匹配到空映射而不是 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
你可以像这样进行模式匹配
def emojify( %{status: 200, resp_headers: %{"Content-Type" => "application/json" } } = conv
) do
%{ conv | resp_body: conv.resp_body }
end
def emojify(%{status: 200} = conv) do
%{ conv | resp_body: "" <> "\n\n" <> conv.resp_body <> "\n\n" <> "" }
end
def emojify(conv), do: conv
您始终可以对映射或结构中特定键的值进行模式匹配
有关更多信息,请查看 joyofelixir。