创建新的保护条款

Chr*_*nzo 17 function elixir pattern-matching

在Elixir中,我将如何为函数创建新的保护条款?显然,我已经看到你不能只在一个when语句中调用任何函数,但是能够做到这样的事情会很好:

defmodule Player do
  def play_card(player), do: []
  def play_card(player) when has_cards(player), do: ...
  # Define has_cards as guard clause?
end
Run Code Online (Sandbox Code Playgroud)

Jos*_*lim 23

简短的回答是:你做不到.

答案很长,你可以定义宏,只要它们是由有效的防护表达式构成的,它们就可以在防护中工作.但对于复杂的防守来说,这是非常重要的,所以除非你真的需要,否则最好避免.

有效防护列表可以在入门指南中找到:http://elixir-lang.org/getting-started/case-cond-and-if.html#expressions-in-guard-clauses

可以在Elixir源代码中找到"复杂"保护宏的示例实现:https://github.com/elixir-lang/elixir/blob/5d34fcdccd20bf38c4f2a13f8adeb78e22b4e74c/lib/elixir/lib/kernel.ex#L1574

  • 另一个很好的例子[在SweetElixir研讨会](https://github.com/cromwellryan/sweetelixir/blob/master/advanced/pattern_matching.md#record-pattern-matching)repo.`is_male`和`is_female`宏被用作守卫. (6认同)

Yaw*_*war 2

您现在可以使用Kernel.defguard/1(或) 来执行此操作:defguardp/1

defmodule Player do
  defstruct [:name, cards: []]
  defguard has_cards(cards) when cards != []

  def play_card(%__MODULE__{cards: cards}) when has_cards(cards), do: []
  def play_card(_player), do: []
end
Run Code Online (Sandbox Code Playgroud)

文档: https: //hexdocs.pm/elixir/Kernel.html#defguard/1

然而,必然性守卫仍然是非常简单的构造,所以你不能真正在其中放入复杂的逻辑。作为参考,以下是您可以放入守卫的内容:https://hexdocs.pm/elixir/master/guards.html#list-of-allowed-expressions