我正在阅读Elixir的命名约定。它声明:
不能在警卫中使用的谓词函数的名称 应该有一个尾随问号(?)而不是is_(或 类似的)前缀。
因此,什么样的功能不能用于守卫?
答案 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 :(粗体是我的)
如前所述,只有该页面中列出的表达式才允许使用防护。但是,我们可以利用宏来编写自定义防护,从而可以简化程序或使其变得更特定于域。 最终,重要的是宏的输出(将被编译)归结为允许的表达式的组合。
跟踪问号(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
。