I think true negation could be developed for functions, I like your approach as semantically appropriate but there is another way and that is to use the function as a custom filter operator. Then using then/else to determine the output, else is in effect the negation of then.
It identifies the exclamation mark ! as an operator prefix and not as part of the function name.
In your list: <$list filter="... [.mentions[this]!.mentions[that]]" ... /> the second function name is the same as the first one – and the internal structure knows about the ! prefix.
\function .mentions(re) [search:title:regexp<re>]
----
test `.mentions`
1: link: <$list filter="[[input-this].mentions[this]]"/>
2: no link <$list filter="[[input-that].mentions[this]]"/>
3: no link: <$list filter="[[input-this].mentions[that]]"/>
4: link <$list filter="[[input-that].mentions[that]]"/>
----
test `!.mentions`
1: no link: <$list filter="[[input-this]!.mentions[this]]"/>
2: link <$list filter="[[input-that]!.mentions[this]]"/>
3: link: <$list filter="[[input-this]!.mentions[that]]"/>
4: no link <$list filter="[[input-that]!.mentions[that]]"/>
-----------
test `.mentions[a]!.mentions[b]`
1: link <$list filter="[[input-this].mentions[this]!.mentions[that]]"/>
2: no link <$list filter="[[input-that].mentions[this]!.mentions[that]]"/>
3: no link <$list filter="[[input-this].mentions[that]!.mentions[that]]"/>
4: no link <$list filter="[[input-that].mentions[that]!.mentions[that]]"/>
5: no link <$list filter="[[input-this].mentions[this]!.mentions[this]]"/>
6: no link <$list filter="[[input-that].mentions[this]!.mentions[this]]"/>
7: no link <$list filter="[[input-this].mentions[that]!.mentions[this]]"/>
8: link <$list filter="[[input-that].mentions[that]!.mentions[this]]"/>
---
---
test with title: `this-that` and `this-thaX`
1: no link <$list filter="[[input-this-that].mentions[this]!.mentions[that]]"/>
2: link <$list filter="[[input-this-thaX].mentions[this]!.mentions[that]]"/>
If a function is defined like my example to return a result if true, otherwise nothing, then the use of then/else or :else filter run, becomes a way to respond to the negative.
Thanks for identifying and documenting this @pmario I thought I had seen negation working in the past when I was teaching myself about the functions.
See also the aforementioned :else filter run, that can be a fully fledged filter that follows the previous one, only if it produced no input, ie the title does not exist. The ..then[]else[something]] sets if the subsequent :else filter run is performed or not. It is swapping the non-output to the output.
It may not be what you are looking for, but it is another form of negating a filter
As demonstrated by @pmario the negation ! is actually possible.