Conditional expression chains in Quest are currently always evaluated in their entirety. This means that the expression "if (true = false and false = true)" would evaluate both "true = false" and "false = true". Not only is it inefficient from a performance standpoint, but it causes more problems when evaluating chaining interdependent conditions. For example, "if (player.object_attribute <> null and player.object_attribute.other_attribute)" generates an error if player.object_attribute is null. Any null check with additional conditions therefore requires an additional layer of nesting, which quickly gets complicated to parse and edit, and is difficult to locate, considering the lack of traceability in the error messages that only appear conditionally.
I tried to fix it myself for a few hours, but couldn't get past compilation issues to test anything. Can we expect a future version to stop evaluating conditional expression chains as soon as one link evaluates to false?
Conditional expression chains in Quest are currently always evaluated in their entirety.
I didn't think this was the case, so I just did a quick test.
if (somefunction(a) and somefunction(b)) only evaluates somefunction(b) if the first one is true. You can easily test this by making a function that prints a message when it's evaluated.
if (somefunction(a) or somefunction(b)) only evaluates the second function if the first is false.
However, if I did
if (a = b and x < y) where x is an int and y is an object, it will generate an error.
b are never compared, because Quest checks for type errors before even attempting to evaluate any part of the expression. You can test this by doing
if (somefunction(a) and GetDisplayName(b)) - any messages printed by somefunction are not displayed; you just get an error complaining that there is no operator
and which works on a boolean and a string.
In your example
if (player.object_attribute <> null and player.object_attribute.other_attribute), there is an error during type checking. The "and" operator only works on two booleans, so Quest attempts to check that the two subexpressions (the operator
<> and the attribute
player.object_attribute.other_attribute) are both booleans before it evaluates either of them.
If you really want to do this, you might be able to do:
if (player.object_attribute <> null and GetBoolean (player.object_attribute, "other_attribute")) which I think will work. Because GetBoolean requires an object and a string, and its arguments are of the right types; and it returns a boolean, which is the type "and" is expecting. Using GetAttribute is a good way to defer errors until a statement is actually evaluated in some cases.