elixir的case语句类似于C语言的switch语句, 如下:
case value do
1 -> :one
2 -> :two
end
但是C语言的case语句可以多个case共享一个处理结果:
switch(value){
case 1:
case 2:
return 0;
}
value是1和2都共享了一个处理结果, 这无法在elixir的case语句中做到, 但是
可以在elixir中做到!
参考kotlin的when语句:
when(value){
1, 2 -> "number"
}
和上面的case语句很像啊, 那是不是可以造一个这样的语法呢?
我们进iex看看(第一条是正常的case语句写法, 第二条是我们想要实现的case语句写法)
太好了, 这是个合法的form
一般我们想在elixir中实现一种语法之前, 先使用quote语句来看看这个语法是否合法
如果合法就会返回解析后的ast了
仔细观察上图的结果, 很容易就看出这2条语句变成了什么样的ast
我们只需要写个macro, 将第二个ast转换为第一个ast就行了
为了不和原有的case冲突, 把这个新语法命名为mcase
defmodule Util
defmacro mcase(value, do: clasuses) do
clasuses =
clasuses
|> Enum.flat_map(fn {:->, line, [match, select]} ->
match |> Enum.map(&{:->, line, [[&1], select]})
end)
quote do
case unquote(value), do: unquote(clasuses)
end
end
end
再写个简单的测试代码
defmodule UtilTest
use ExUnit.Case
import Util
test "mcase" do
a =
mcase 1 do
1, 2 -> :ok
3 -> :error
end
assert a == :ok
end
运行测试, 通过
这样我们就简单的实现了一个新语法!