我在这种风格中做了相当多的模式匹配:
def action(%{start_date: start_date, amount: amount, notify: notify %}) do
# some action
end大多数情况下,我为参数选择的名称在映射中是相同的。有没有一种快捷方式可以指定模式匹配大小写,而不会重复键和值的相同名称?
下面这段伪代码中的内容如下:
def action(%{start_date: %s, amount: %s, notify: %s}) do
IO.inspect(start_date)
# some action
end发布于 2017-06-01 14:38:39
AFAIK,没有什么是开箱即用的,但人们可以简单地为自己创建一个宏来服务于此目的:
defmodule M do
defmacro struct(params) do
{:%{}, [], Enum.map(params, fn e -> {e, {e, [], Elixir}} end)}
end
end
defmodule Test do
require M # to use macro
def action(M.struct([:a, :b]) = params),
do: IO.inspect params, label: "Params are"
end
Test.action(%{a: 42, b: :ok})
#⇒ Params are: %{a: 42, b: :ok}
Test.action(%{a: 42})
** (FunctionClauseError) no function clause matching in Test.action/1上面的代码当然只是一个MCVE,你可能需要以某种方式增强它,以更优雅地处理边角情况(并且,很可能,拥有更明确的可读宏,它的行为比仅仅是输出AST更智能,并考虑到绑定等),但我相信这解释了这个想法。
发布于 2017-06-02 13:29:23
我引入了一个符号~m{...}来实现析构任务。
~m{foo bar} = %{foo: 1, bar: 2}
foo #=> 1
bar #=> 2下面是我如何实现sigil
defmodule DestructingAssignment do
defmacro __using__(_) do
quote do: import unquote(__MODULE__)
end
defmacro sigil_m({:<<>>, _line, [string]}, []) do
spec = string
|> String.split
|> Stream.map(&String.to_atom/1)
|> Enum.map(&{&1, {&1, [], nil}})
{:%{}, [], spec}
end
end使用
defmodule Foo do
use DestructingAssignment
def foo(~m{bar}) do
# Do whatever you want with bar
IO.inspect(bar)
end
end
Foo.foo(%{bar: 1, baz: 2})
1https://stackoverflow.com/questions/44299600
复制相似问题