[erlang-questions] Guards syntax for multiple values

José Valim jose.valim@REDACTED
Wed Mar 27 02:17:01 CET 2019


> Everybody seems to be chasing after how to express "X in [...]" as a guard
without responding to the suggestion of copying SML/NJ's "or patterns"

What are the restrictions for OR patterns?
Can OR patterns be allowed anywhere in a pattern (i.e. arbitrarily nested)
or are they allowed only at the root?
Can we bind variables inside OR patterns?

I assume both are possible as long as after all combinations are expanded,
they all bind the same variable names?

> I am also puzzled that nobody seems to be concerned that the one and only
example we have of a use case is code that should never be written in the
first place

Since we do have this feature in Elixir, I can provide examples of where we
use it in the language, translated to Erlang.
I will use the is_member/2 syntax but anyone is welcome to translate it to
"X in Y" or the equivalent "OR patterns".

*Example 1: validate supervision restart*

validate_restart(_Name, Strategy)
    when is_member([permanent, temporary, transient], Strategy) ->

  ok;

validate_restart(Name, Strategy) ->

  error({bad_strategy, Name, Strategy}).


Without is_member, you either need multiple clauses (which is ok in this
case, since the positive clauses only return ok) or write long guards (too
repetitive IMO).

*Example 2: rewriting Erlang binary operators into Elixir AST*

rewrite_guard_call(Op)
    when is_member(['band', 'bor', 'bnot', 'bsl', 'bsr', 'bxor'], Op) ->

  {'.', meta(), [bitwise, Op]};

rewrite_guard_call(Op) ->

  ...N other clauses...


I find this a very good example of is_member/2. Of course, the
functionality could be written differently, but I can't think of any
alternative existing *today* that would be as concise or as elegant as
is_member/2.

*Example 3: Checking if a character is unreserved according to URI (RFC
3986)*

Similar to the Unicode example except we are pinned against a RFC, so it
can't change:

char_unreserved(Char)
    when Char >= ?0, Char =< ?9;
         Char >= ?A, Char =< ?Z;
         Char >= ?a, Char =< ?z;

         is_member("~_-.", Char) ->
  true;

char_unreserved(Char) when Char >= 0, Char <= 16x10FFFF ->

  false.


And similar for reserved characters:

char_reserved(Char)
    when is_member(":/?#[]@!$&\'()*+,;=", Char) ->

  true;

char_reserved(Char) when Char >= 0, Char <= 16x10FFFF ->

  false.


There are likely other examples but this should be enough to push the
discussion forward.

*José Valim*
www.plataformatec.com.br
Skype: jv.ptec
Founder and Director of R&D
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20190327/2356af2c/attachment.htm>


More information about the erlang-questions mailing list