如何在保护条款中使用elixir中的按位运算符?

时间:2017-06-08 14:46:13

标签: pattern-matching elixir

我有以下函数,只需要匹配n的值是2个整数(1, 2, 4, 8, 16, 32, 64, ...)的幂:

defmodule MyModule do
  def my_func(n) when is_power_of_two(n) do
     ## Some expression
  end
  def is_power_of_two(x) do
    (x != 0)
        and (x &&& (x - 1)) == 0)
  end
end

首先,我尝试将is_power_of_two定义为模块中的一个函数,但它没有工作,我收到了这个错误:

cannot invoke local is_power_of_two/1 inside guard

blog post之后,我尝试将其定义为以下宏:

defmodule MyModule.Util do
  defmacro is_power_of_two(x) do
    quote do
      (unquote(x) != 0)
        and ((unquote(x) &&& (unquote(x) - 1)) == 0)
    end
  end
end

我也没有工作,我收到以下错误:

cannot invoke local &&&/2 inside guard

在宏扩展之后,似乎无法从&&&子句调用按位when运算符。

如何执行需要包含按位运算符的保护的匹配?

1 个答案:

答案 0 :(得分:2)

错误消息具有误导性。您在import Bitwise中错过了MyModule.Util。如果我添加import

,代码就可以使用
defmodule MyModule.Util do
  import Bitwise

  defmacro is_power_of_two(x) do
    quote do
      (unquote(x) != 0) and ((unquote(x) &&& (unquote(x) - 1)) == 0)
    end
  end
end

defmodule MyModule do
  import MyModule.Util

  def my_func(n) when is_power_of_two(n) do
    true
  end
  def my_func(_), do: false
end

IO.inspect MyModule.my_func(128)
IO.inspect MyModule.my_func(129)

输出:

true
false