<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">On Wed, Mar 27, 2019 at 2:17 AM José Valim <<a href="mailto:jose.valim@plataformatec.com.br">jose.valim@plataformatec.com.br</a>> wrote:<br></div></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">> <span style="font-family:monospace,monospace">Everybody seems to be chasing after how to express "X in [...]" as a guard</span></div><div style="font-family:monospace,monospace">without responding to the suggestion of copying SML/NJ's "or patterns"</div><div dir="ltr"><br></div><div>What are the restrictions for OR patterns?</div><div>Can OR patterns be allowed anywhere in a pattern (i.e. arbitrarily nested) or are they allowed only at the root?</div><div>Can we bind variables inside OR patterns?</div><div><br></div></div></div></div></div></div></div></blockquote><div><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">I'll use Ocaml as the language for this, since it has the same pattern as SML/NJ, and I happen to have Ocaml installed, but not SML/NJ.</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">In erlang we write:</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">case Exp of</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">  P1 -> E1;</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">  P2 -> E2;</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">  P3 -> E3</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">end</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">In Ocaml, we would write</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">match Exp With</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">| P1 -> E1</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">| P2 -> E2</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">| P3 -> E3</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">Note that we prefix each pattern by '|' rather than separate them with ';' as in Erlang. The semantics are otherwise the same at least up to a very high level of equivalence. Now suppose, we have a case where we want to write</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">match Exp with</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">| P1 -> E</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">| P2 -> E</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">| P3 -> E3</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">That is, both patterns P1 and P2 runs the same function body E. In this case, Ocaml allows us to avoid the repetition, the so-called OR-pattern:</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">match Exp with</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">| P1 | P2 -> E</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">| P3 -> E3</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">What are the rules? Any use of a variable 'x' in E must be bound in the scope and must have the same type. That is, if P1 binds 'x : t' i.e., with type t, then P2 must also bind 'x : t'. In principle, we could allow it if the scope/context has 'x : t' and it isn't bound in P2, but this is currently rejected by the language, probably on the grounds of being prone to error.</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">The compiler has a relatively easy rewrite to make:</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">let body_E x = E in</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">  match Exp with</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">  | P1 x -> body_E x</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">  | P2 x -> body_E x</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">  ...</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">more or less (caveat: capture! body_E must be be passed parameters appropriately if it uses them from the context. Further optimizations might then lift them). Extract the common body into a local function and apply that function. Further optimizations are often able to remove 'body_E' from the generated code. Since we are in ML-land with Standard ML and Ocaml, the Mlton compiler has a contification optimization which will fuse the body_E continutation appropriately. This can then uncover further optimizations down the road.<br></div><br></div></div>