WeakAuras

WeakAuras

206M Downloads

Add nil check and logical negation to conditions

0xjc opened this issue ยท 6 comments

commented

(1) It would be useful to have an "is nil" and "is not nil" check in WeakAura conditions, available for all variable types.

For example, if {x = "number"} is a custom variable and the value of x is nil, then all of the currently available checks like x == 0 and x != 0 will return false. Since a variable being nil/not nil is a common and natural way of representing certain states, it would be very useful to be able to directly check for it in conditions.

While there exist workarounds in some cases - e.g. if x is a number, testing Any of {x == 0, x != 0} would be equivalent to x is not nil - this is both cumbersome and cannot positively express the condition x is nil.

(2) It would be useful to have a "Not" option in WeakAura conditions, in addition to the existing "All of" and "Any of" options.

While the "Not" option is not necessary for something like not (x == 0) as it can be expressed as x != 0, there are some conditions that don't have their negations registered as options. E.g. for strings we have "Is Exactly", "Contains", and "Matches", but there aren't any options for "Is Not Exactly", "Does Not Contain", "Does Not Match". I'm aware that it's sometimes possible to get around this by negating the property change, e.g. if you want your aura to glow if not [condition] then you can the glow to be enabled by default and set it to not glow if [condition]. However this solution doesn't always apply, and even when it does work it can obfuscate the intent of the condition.

A simple example of a condition that cannot currently be expressed is: string s contains "a" but does not contain "b". Negating the property change won't work because the overall negation has the same logical structure: string s contains "b" but does not contain "a".

Another example that cannot currently be expressed is x is nil and y is not nil. While it is possible to express the y is not nil part by selecting Any of {y == 0, y != 0}, it is not currently possible to express the x is nil part. Negating the property change won't help for the same reason as the previous example.

Also, while it is possible to patch around this by adding in the logical negations to everything (like "Is Not Exactly", etc.), I believe it would still be a good idea to add the "Not" option. It is a simple feature and it would make WA conditions into a functionally complete boolean calculus (having the set "And" + "Or" is incomplete without "Not").

commented

I guess I can give a fuller explanation of why NOT is not needed for a general system.

First of all, every boolean experssion has a CNF and DNF form. Note, that in these forms there's no NOT that applies to any conjuction or disjunction, NOT only exists at the literal level.

The literals for conditions are the individual checks. For these checks, in general the reverse check is available. Instead of making literals negatable, checks can be reversed.

You correctly pointed out that this is not the case for string operations. I do think that adding "not contains", and/or "not exactly" would make it the string operations more complete.

They need to be motivated by concrete use cases, but they are very much how the system is designed to work.

The second issue, that you also correctly pointed at is, that "nil" is not supported. That's because it's a confussing concept for users, and rarely useful. Now, if there's more than just charges that need that, then maybe there's something missing. At the moment I'm unconvinced that there's a lot of use cases for checking against nil.

There are multiple problems with adding a nil checks (even without thinking to long about it):

  • It leads people to assume that they need it, because in custom code you'd add it naturally.
  • The type system for states is not powerful enough to express that concept. Maybe it should, maybe it shouldn't. There are some special cases for numbers that point out to a general problem with the concept of the "number" type.
commented

Thanks for the explanations. While I still overall disagree on the issue I understand your rationale more clearly now.

You were right that if...else if clauses with empty bodies can always create equivalent expressions to boolean expressions with the NOT operator. However, doing this can be quite awkward and unintuitive. Imagine if Lua had omitted the not operator because you can always achieve the equivalent effect with a sequence of if and elseif clauses with empty bodies. Although it technically has the same expressive power, it becomes much more frustrating to use. (Also, regarding CNF and DNF, converting to those forms can cause an exponential explosion in formula length in the worst case.) Similarly for the nil checks - imagine if for every nilable variable foo you had to have an auxiliary boolean variable isFooNil to check for nil; you could do it but it would be tedious and inelegant.

I would love to use custom checks as my go-to in order to bypass these restrictions, but unfortunately it doesn't automatically schedule timers for a condition like Remaining Duration < 5, making it hard to use for such checks. So I guess I am stuck with these workarounds.

commented

This is both too fringe and you are are wrong on these not being expressable.

There are 3 methods:

  • Simply modify your trigger to have a boolean for your nil/not nil or not contains check
  • Use a custom check
  • Use "else if true" to negate a check, that is:
    not condition is:

If condition then

  • Empty property changes

Else if Always true

  • property changes
commented

What this feature requests really lacks is good use cases for any of these checks. It presents a solution, without describing any problems.

commented

Maybe we could have an actual discussion then, instead of summarily closing the issue? This is not the first time I've spent time and effort crafting an issue only for you to immediately close it with a short comment. Perhaps another one of the other WeakAura developers could take a look?

This is not some crazy feature I'm asking for. It seems quite reasonable to want a framework for testing logical conditions to support the logical NOT operator, and also to be able to check whether a nilable variable is or is not in fact nil.

  • Adding another boolean variable works for custom variables, but it's cumbersome. Also, this won't help for built-in triggers. To give one example, with the Cooldown Progress (Spell) trigger, the Total Charges variable is nil if the spell doesn't use charges, and it can be useful to test whether or not this is the case.
  • I'll look into custom checks (particularly if this issue isn't resolved), but it seems useful for non-coder WeakAura authors to also be able to access this functionality.
  • The "else if true" trick negates the whole condition, running into the same problem as negating the property change that I described in the OP.

I would be willing to contribute a pull request if it's simply a matter of lack of dev effort/interest.

commented

Well, the amount of work you put into the issue, does not make your observations any truer or your feature request any better.

Not including any use cases that are cumbersome is a fatal blow to any feature request. The aim of WeakAuras is not some kind of perfect system, but a usable system for power users to create powerful stuff.

In particular it was a delibrate choice to not include NOT in the set of operations. Instead I decided after some thought that pushing NOT towards the individual checks, which is equally powerful but much better for user accesibility than any design that I considered with NOT included.

As to Total Charges, you can do:
"If total charges > -1"
which is always true for spells with charges.

As to Else if, that is together with the other combinations strictly as powerful as supporting NOT.

For example:
string s contains "a" but does not contain "b"

=>
If contains b then
Else if string contains a then
=> Property changes

Those property changes will be applied if the string contains a but not b.