问号和Elixir函数名称中的“is_”

时间:2017-02-20 09:57:27

标签: elixir

我正在阅读Elixir的命名约定。它声明:

  

不能在警卫中使用的谓词函数的名称   应该有一个尾随问号(?)而不是is_(或   类似的)前缀。

因此,什么样的功能不能用于守卫?

3 个答案:

答案 0 :(得分:5)

这三个函数都包含在守卫中有效的表达式;它只是自定义防护必须写成宏,而不是正常的功能:

defmodule User do
  defstruct age: 0

  defmacro kid?(age) do
    quote do
      6 < unquote(age) and unquote(age) < 12
    end
  end

  defmacro teen?(age) do
    quote do
      12 < unquote(age) and unquote(age) < 18
    end
  end

  defmacro elder?(age) do
    quote do
      60 < unquote(age)
    end
  end
end

defmodule Greeting do
  import User

  def greet(%{age: age}) when kid?(age), do: "Hiya"
  def greet(%{age: age}) when teen?(age), do: "Whatever"
  def greet(%{age: age}) when elder?(age), do: "You kids get off my lawn"
  def greet(_), do: "Hello"
end

for age <- [0, 5, 10, 15, 20, 90] do
  IO.inspect {age, Greeting.greet(%{age: age})}
end

输出:

{0, "Hello"}
{5, "Hello"}
{10, "Hiya"}
{15, "Whatever"}
{20, "Hello"}
{90, "You kids get off my lawn"}

答案 1 :(得分:0)

可以在警卫here中使用的完整功能列表。如果该函数不在该列表中,则不能在保护条款中使用它,除非像Dogbert在上面指出的那样创建一个符合他所规定的规则的自定义保护功能。

编辑:

请参阅此page

  

一组有效的保护表达式(有时称为保护测试)   是有效Erlang表达式集的子集。的原因   限制有效表达式的集合是对警卫的评估   必须保证表达没有副作用。

重点放在原文中。

因此,必须保证您用作防护(内置或宏)的任何功能都没有副作用。由于难以保证,Erlang VM本身限制了哪些表达式可用于防护。如果您编写自己的宏,它最终会被渲染为Elixir代码,如果Elixir代码不符合有关守卫的规则,无论是否宏,它都不会起作用。

我希望这会让事情变得更清楚。

答案 2 :(得分:0)

Elixir 1.7.3 documentation :(粗体是我的)

如前所述,只有该页面中列出的表达式才允许使用防护。但是,我们可以利用宏来编写自定义防护,从而可以简化程序或使其变得更特定于域。 最终,重要的是宏的输出(将被编译)归结为允许的表达式的组合。

并且来自Naming Conventions doc,

跟踪问号(foo?) 返回布尔值的函数以结尾的问号命名。 示例:Keyword.keyword?/1、Mix.debug?/0、String.contains?/ 2 但是,返回布尔值并在后卫中有效的函数遵循另一种约定,如下所述。

is_前缀(is_foo) 保护子句中允许的类型检查和其他布尔检查均以is_前缀命名。 示例:Integer.is_even / 1,Kernel.is_list / 1 这些函数和宏遵循is_前缀的Erlang约定,而不是尾随的问号,以精确地指示它们在保护子句中是允许的。 请注意,在保护子句中无效的类型检查不遵循此约定。示例:Keyword.keyword?/1、Regex.regex?/ 1

因此,对于写入兼容的保护宏(如果它们没有副作用),可以使用列出的表达式之一返回boolean