1

我可以使用警卫来测试参数是否为true

defmodule Truth do
  def true?(term) when term, do: "#{term} is true"
  def true?(term), do: "#{term} is not true"
end

这对布尔值按预期工作:

Truth.true?(true)
#=> "true is true"
Truth.true?(false)
#=> "false is not true"

但它无法测试其真实性:

Truth.true?(1)
#=> "1 is not true"

是否可以测试警卫的真实性?例如,下面的函数可以使用上述风格的守卫来编写true?/1吗?

def truthy?(term) do
  if term, do: "#{term} is truthy", else: "#{term} is falsey"
end
4

1 回答 1

4

根据Guards 的官方文档

守卫以when关键字开头,后跟一个布尔表达式。

所以守卫中的表达式必须是布尔表达式。

长生不老药中的真实性由宏定义,例如if/2. 这些宏在守卫内部不可用,因此我们需要另一种方法将术语转换为布尔值。

我们可以从文档(和实现)中看到,if/2真实性的定义是虚假的,其他一切都是真实的。所以我们可以用它来实现我们的真实性守卫:falsenil

defmodule Truth do
  defguard is_falsey(term) when term in [false, nil]
  defguard is_truthy(term) when not is_falsey(term)

  def truthy?(foo) when is_truthy(foo), do: "#{foo} is truthy"
  def truthy?(foo), do: "#{foo} is falsey"
end

然后按预期工作:

Truth.truthy?(true)
#=> "true is truthy"
Truth.truthy?(1)
#=> "1 is truthy"
Truth.truthy?(false)
#=> "false is falsey"
Truth.truthy?(nil)
#=> " is falsey"
于 2019-09-25T00:44:53.113 回答