我刚刚介绍了Elixir的基础知识,并决定使用元编程获得一些乐趣。在Chris McCord的书中,有以下定义我们自己的unless
结构的例子:
defmodule ControlFlow do
defmacro unless(expression, do: block) do
quote do
if !unquote(expression), do: unquote(block)
end
end
end
我似乎无法理解unless(expression, do: block)
部分。我遇到的do:
构造的唯一用途是缩短函数体并将其压缩成一行。但是,这里,unless
之后执行的块已经是函数参数的一部分。 do: block
部分如何适应这里?也许我只是忽略了一些非常简单的东西,但我很乐意指出它。
答案 0 :(得分:1)
:do
只是简单的模式匹配,可以轻松提取传递给关键字参数defmacro unless(expression, [do: block])
的值。它等同于:
defmacro unless(expression, [{:do, block}])
简称:
iex(1)> [do: block] = [do: 123]
[do: 123]
iex(2)> block
123
并且表现得像你期望的那样:
unless
您还可以重写defmodule ControlFlow do
defmacro unless(expression, args) do
quote do
if !unquote(expression), do: unquote(args[:do])
end
end
end
以不使用这样的模式匹配:
do:
这并不完全等同于原始代码,因为它会默默地忽略#!/etc/bash
test_word=' ' # test_word includes only one space
if [[ ${test_word} =~ ^\s*$ ]]; then
echo "detect"
else
echo "not detect"
fi
参数的缺失,但很容易修改代码以支持它。