*Continuing the discussion from… Expat - composable, reusable pattern matching*

That’s a compelling idea. Thinking out loud about this from a semantics approach.

### In arguments

If we allow that then I think it makes sense to allow guards to be arbitrarily deep in the arguments list, for instance inside data structures:

```
def pos_distance({x when is_integer(x), y when is_integer(y)}) when x + y > 0 do
:math.sqrt(:math.pow(x, 2) + :math.pow(y, 2))
end
```

This is the most blatant point of contention I can think of. The alternative is to require that internal guards be trailing a parameter rather than any further in the AST.

Logically you’d expect internal guards to be `and`

-ed with trailing ones, ie:

```
when (internalGuard1 && internalGuard2) && trailingGuards
```

### Scoping

Trailing guards benefit from not having to be aware of scoping, so that this typo is impossible:

```
def pos_distance({x when is_integer(y), y when is_integer(x)}) when x + y > 0 do
:math.sqrt(:math.pow(x, 2) + :math.pow(y, 2))
end
```

I’m not sure how that should be handled.

### Mutli-guard functions

How would we handle multiple trailing guards? My understanding is that they are not often used, but logically equivalent to `or`

-ing each one together (with different exception behaviours that make certain things possible). So a naive macro might try:

```
when internalGuards && (multiguard1 || multiguard2)
```

However that doesn’t preserve the exception behaviour, so the correct macro rewrite would have to be

```
when internalGuards && multiGuard1
when internalGuards && multiGuard2
```

### Internal multi-guards

This also invites speculation about the opposite construct, how would we resolve the non-sensical inner multi-guard after the point in the example:

```
def pos_distance({x, y} when x > 0 when y > 0, pow when is_integer(pow)) when x + y > 0 do
:math.sqrt(:math.pow(x, pow) + :math.pow(y, pow))
end
```

I can’t think of an intuitive way to handle this without making the rewrite explode exponentially for every permutation of each set of inner multiguards and trailing multi-guards. I think nested `when`

s in the AST would have to raise syntax errors early within arguments lists.

### In cases

I think the construct makes sense for cases as well as functions, though it’s even uglier when written by hand in daily use:

```
case point do
{x when is_integer(x), y when is_integer(y)}) when x + y > 0 ->
:math.sqrt(:math.pow(x, 2) + :math.pow(y, 2))
_ -> 0
end
```

It might come in handy in some really deep matching that you’ve chosen to spread across multiple lines rather than refactor, though.