less/less.js — pull request #1584 by bsl-zcs (2013-10-06 19:11:32+00:00)
Title: Mutually exclusive pattern matching support

LESS provides a means to conditionally restrict application of mixin via pattern matching. Additional treatment for special cases can be extracted to separate pattern matched mixin, but there is currently no easy way to suppress application of common case rules in a special case.

This behavior is a source of confusion (e.g. #746) and probably is the most significant cause of an overall low usage of pattern matching.

As a workaround, there can be declared a variable, which is assigned inside each special case mixin, and its value is checked later in guard condition of the common case mixin. But mixin call results get imported to caller ruleset as a whole, and they can’t affect variables of each other. Thus common case mixin must be named differently and called separately.

At the moment my best attempt looks like that:
```less
.bg(@color) {
.bg-special(@_) { @matched: false; }
.bg-special(ok) { background: green; @matched: true; }

.bg-default(@color) when not (@matched) { background: @color;}

.bg-special(@color);
.bg-default(@color);
}
.test {
.bg(red);
.bg(ok);
.bg(blue);
}
```

The best way I found to simplify such constructs by modifying LESS is to place additional variable, indicating previous success of mixin application, into environment while evaluating guard condition of the next mixin. Then it can be simply checked inside the guard expression. Definition, entirely equivalent to the first example, reduces to:

```less
.bg(ok) { background: green; }
.bg(@color) when (@NoOtherMatches) { background: @color;}
```

Downside here is that, as far as I know, LESS previously had no notion of special variables. I’ve tried to minimize potential conflicts by limiting area of variable visibility – it’s available only in guard conditions – but collision is unlikely yet possible. Probably it is a lesser evil than to introduce a new syntactic construct for that purpose.

Anyway, I’ll be glad to hear suggestions of better ways to do it, or at least a better name to that variable. :)