Add community knowledge: AL boolean operators do not short-circuit - #136
Add community knowledge: AL boolean operators do not short-circuit#136António Silva (aacnsilva) wants to merge 4 commits into
Conversation
AL gives no short-circuit (lazy) evaluation guarantee for and/or/xor — neither the AL operators nor the boolean operators documentation defines a lazy evaluation order. LLMs trained on C#, JavaScript, or SQL assume the left operand guards the right, which produces conditions where a guard does not protect an unsafe subscript or a field read after a failed Get, and where an expensive operand is paid on every path. Adds community/knowledge/performance/boolean-operators-do-not-short-circuit.md with good/bad AL companions. The guidance prefers nested if when one operand depends on another, while keeping and/or legitimate for operands that are independently safe and cheap, so a reviewer does not flag harmless bound checks. This is the first article in a community performance domain; the Microsoft performance review leaf skill already sources candidates by domain across every enabled layer, so no skill change is needed to reach it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Some people prefer to use the in operator to short-circuit/lazy evaluate but AL developers are most used to seeing if statements and the in operator might confuse more than help, at least in the beginning, so I added nested if conditions instead in the knowledge file and good pattern. |
Natalie Karolak, MVP (NKarolak)
left a comment
There was a problem hiding this comment.
Nice one!
Mind that for a long enumeration of if to follow, the case true of or case false of pattern might be interesting as well.
https://nataliekarolak.wordpress.com/2022/12/21/lazy-evaluation-in-al/
|
Great suggestion, will add that so that we don't end up with more than 3 nested if statements. I'm used to use the in operator (same thing as the case true/false of) but I agree that developers will feel/be more comfortable or at home with the case of. |
Follow-up from PR review: nested if is the right answer for two or three dependent conditions, but past that the nesting becomes the problem. AL's case statement is the flat alternative — the control statements documentation states a value set "must be an expression or a range" and that the first matching value set executes, so case true of / case false of accept boolean expressions and stop at the first match. That is the laziness the boolean operators do not provide. Adds case-true-of-for-long-condition-chains.md with good/bad AL companions: case false of for guard chains where every condition must hold, case true of for first-match dispatch. The bad sample shows both failure shapes — a five-level if ladder, and the worse escape of collapsing it into an and chain, which trades nesting for a real defect. Cross-links both articles, and adds the threshold to the short-circuit article's Best Practice so following it does not lead to a deep ladder. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review feedback: the five value sets sharing exit(false) should be comma separated. Applied to the three that are pure field reads with no order dependency. The Get and the Blocked read keep their own value sets. The documentation guarantees that the first matching value set executes, which orders matching across separate value sets; it says nothing about evaluation within one comma-separated set, and the natural lowering of that is an equality-or chain — where AL's or does not short-circuit. Grouping the Get with the checks that must precede it would rest the sample's correctness on undocumented behaviour, which is the defect these two articles exist to prevent. Encodes the boundary in the Best Practice section so the grouping is applied where it is safe and not where it is not, and scopes the repeated-exit detection signal explicitly to nested chains so the case sample does not read as its own anti-pattern. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review decision: all five conditions share one action, so they share one comma-separated value set with a single exit(false). Aligns the article's Best Practice with the sample — it previously told authors to keep side-effecting conditions in their own value set, which the sample no longer does — and drops the now-contradictory wording about listing the failure action per condition. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
What
Adds
community/knowledge/performance/boolean-operators-do-not-short-circuit.md, with.good.al/.bad.alcompanions.AL gives no short-circuit (lazy) evaluation guarantee for
and,or, andxor. Code must therefore not use the leftmost operand as a guard for a later one, and must not expect a costly operand to be skipped once the result is decided. The fix is a nestedif— guard outermost, dependent or expensive condition inner.Why this passes the admission test
An LLM trained mostly on C#, JavaScript, or SQL carries short-circuiting in as a default assumption, and BC has no compiler diagnostic that contradicts it. That produces two failure shapes the file prevents:
(Index >= 1) and (Index <= ArrayLen(Thresholds)) and (Amount > Thresholds[Index])still evaluates the subscript. LikewiseCustomer.Get(No) and (Customer.Blocked <> ...)readsBlockedfrom a record that was never loaded — a silently wrong result rather than an error.andwhose left operand is alreadyfalse.Note on the documentation
Neither AL operators nor Boolean operators mentions short-circuit or lazy evaluation in either direction. The article is therefore worded as no guarantee is given, so do not rely on one, rather than asserting a documented evaluation order. That yields the same guidance without claiming platform behaviour the docs do not state — and is part of why this went to
/community/rather than/microsoft/.🤖 Generated with Claude Code