【问题标题】:Arbitrary arguments in Elixir Macros - wrapping a bodyElixir Macros 中的任意参数 - 包裹身体
【发布时间】:2016-02-10 03:29:16
【问题描述】:

我正在开发一个处理 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 宏中。

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

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

提前致谢。

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

【问题讨论】:

  • 您的setget 函数是什么样的?似乎可以编写其中一个或两个来返回错误,然后您就不需要宏了。
  • @CoderDennis 他们很容易被重写——问题是除了setget之外还有N个函数——我不想重复写N次。

标签: macros elixir


【解决方案1】:

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

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

【讨论】:

  • 我认为使用unlesselse 比使用'if' 和翻转分支更难理解。除此之外,我认为这看起来不错。
  • @PatrickOscity 好的很酷,谢谢 :) 通常我会同意 if,但我个人更喜欢先解决错误情况,这样你就可以立即看到任何简短的 -电路。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-05
  • 1970-01-01
  • 1970-01-01
  • 2014-07-30
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
相关资源
最近更新 更多