Elixir 宏中的任意参数 - 包裹body



我正在开发一个处理 ETS 的小型库,如果表不存在,我希望能够提前退出函数。我不能把它放在守卫中,因为 Elixir 阻止在守卫中与:ets交谈,所以我必须基本上在每个函数中都放这个检查,最终看起来像这样可怕的东西(代码是演示 - 我知道它很混乱:)):

def get_and_update(cache, key, modifier) do
  unless is_ets_table(cache) do
    { :error, create_error(cache) }
  else
    set(cache, key, modifier.(get(cache, key)))
  end
end

有没有办法将其宏化为以下内容?

deftable get_and_update(cache, key, modifier) do
  set(cache, key, modifier.(get(cache, key)))
end

对缺少表的检查将隐式地存储在deftable宏中。

我已经阅读了宏,但我似乎无法弄清楚到底发生了什么,所以如果你能解释你的答案,我将不胜感激。

除了混乱之外,我还想让开发人员更容易只使用宏名称,而不必总是记住检查表。

提前谢谢。

编辑:我还应该注意,参数的数量可以很容易地(并且会)改变。

我按如下方式实现了这一点,但如果有更好的方法,请告诉我:

defmacro deftable({ func_name, _func_ctx, [cache|_] = args }, do: body) do
  quote do
    def unquote(func_name)(unquote_splicing(args)) do
      if not is_ets_table(unquote(cache)) do
        unquote(body)
      else
        { :error, no_table(unquote(cache)) }
      end
    end
  end
end

最新更新