Create new guard clause

雨燕双飞 提交于 2019-12-05 11:02:47

问题


In Elixir, how would I go about creating a new guard clause for a function? Obviously, I've seen that you can't just call any function in a when statement, but it would be nice to be able to do something like this:

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

回答1:


You can use Kernel.defguard/1 (or defguardp/1) to do this now:

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

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

However, guards of necessity are still very simple constructs, so you can't really put complex logic in them. For reference, here's what you can put in guards: https://hexdocs.pm/elixir/master/guards.html#list-of-allowed-expressions




回答2:


The short answer is: you can't.

The long answer is that you can define macros and they will work in guards as long as they are made of valid guards expressions. But that is non-trivial for complex guards so it is better avoided unless you really have to.

The list of valid guards can be found in the getting started guide: http://elixir-lang.org/getting-started/case-cond-and-if.html#expressions-in-guard-clauses

A sample implementation of a "complex" guard macro can be found in Elixir source: https://github.com/elixir-lang/elixir/blob/5d34fcdccd20bf38c4f2a13f8adeb78e22b4e74c/lib/elixir/lib/kernel.ex#L1574



来源:https://stackoverflow.com/questions/21261696/create-new-guard-clause

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!