From iris-dev
Teaches correct ObjectScript loop patterns including $Order iteration, postfix Quit, and Return vs Quit for early exits. Helps avoid parse errors and logic bugs when writing loops.
How this skill is triggered — by the user, by Claude, or both
Slash command
/iris-dev:objectscript-loop-patternsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
```objectscript
// Quit with value inside a For/While loop → EXITS THE LOOP, not the method
// The method continues after the loop and returns whatever Quit returned... actually ""
// WRONG — Quit 0 inside For exits the loop, method returns "":
ClassMethod IsUnique(name As %String, lst As %ListOfDataTypes) As %Boolean
{
For i=1:1:lst.Count() {
If (lst.GetAt(i) = name) {
Quit 0 // exits loop, NOT method — method returns ""!
}
}
Quit 1 // only reached after loop completes
}
// CORRECT — Return always exits the method:
ClassMethod IsUnique(name As %String, lst As %ListOfDataTypes) As %Boolean
{
For i=1:1:lst.Count() {
If (lst.GetAt(i) = name) {
Return 0 // exits method immediately with 0
}
}
Return 1
}
// Iterate all keys of a local array:
Set key = ""
For {
Set key = $Order(arr(key))
Quit:key="" // ← postfix Quit, ALONE on its own line, NO SPACES around =
// process arr(key)
}
// WRONG — spaces in postfix condition:
Quit:key = "" // ← #5559 parse error!
// WRONG — postfix Quit on same line as anything else:
Set key = $Order(arr(key)) Quit:key="" // ← #5559 parse error!
Return value Quit:key="" // ← #5559 parse error!
// Remove items during iteration — always go backwards:
For i=items.Count():-1:1 {
If (items.GetAt(i) [ "DELETE") {
Do items.RemoveAt(i)
}
}
// items.Count():-1:1 means start=Count(), step=-1, end=1
// Forward iteration:
Set key = $Order(^MyGlobal("")) // "" seed gives FIRST key
While key '= "" {
// process ^MyGlobal(key)
Set key = $Order(^MyGlobal(key))
}
// WRONG — no subscript:
Set key = $Order(^MyGlobal) // ← <FUNCTION> error!
// Reverse iteration:
Set key = $Order(^MyGlobal(""), -1) // last key first
While key '= "" {
Set key = $Order(^MyGlobal(key), -1)
}
// Count up:
For i=1:1:10 { ... } // 1,2,3,...,10
// Count down:
For i=10:-1:1 { ... } // 10,9,8,...,1
// Infinite with explicit Quit:
For {
// ...
Quit:condition
}
// Over a comma-separated list (not common but valid):
For i=1,3,7 { write i,! } // 1, 3, 7
When escaping HTML, always escape & FIRST:
// WRONG — & escaped last causes double-escaping:
// "<b>A & B</b>" → "<b>A & B</b>" → "<b>A & B</b>" ← wrong
// CORRECT — & first:
Set safe = $REPLACE(message, "&", "&") // 1. ampersands first
Set safe = $REPLACE(safe, "<", "<") // 2. then less-than
Set safe = $REPLACE(safe, ">", ">") // 3. then greater-than
// optional: Set safe = $REPLACE(safe, """", """)
// WRONG — modifying i inside the loop causes skipped/repeated iterations:
For i=1:1:items.Count() {
If condition { Set i = i + 1 } // skips next item — DON'T DO THIS
}
// CORRECT — use a separate flag or backwards iteration:
Set i = 1
While i <= items.Count() {
If condition {
Do items.RemoveAt(i) // don't increment — list shrunk
} Else {
Set i = i + 1
}
}
// OR — backwards loop (simpler):
For i=items.Count():-1:1 {
If condition { Do items.RemoveAt(i) }
}
## 8. Global Negative-Key Trick — Descending Sort Without a Sort Step
IRIS globals sort subscripts ascending by default. To iterate in descending order
by a numeric score, store the **negated** value as the subscript key. `$Order` then
visits higher scores first.
```objectscript
// Store: negate the score so high scores sort first
Set ^||TagScores(-score, tag) = ""
// Iterate descending — $Order walks negative numbers most-negative first,
// so -100, -90, -80 ... means scores 100, 90, 80 ...
Set key = ""
For {
Set key = $Order(^||TagScores(key))
Quit:key=""
Set tag = $Order(^||TagScores(key, ""))
Write "Score: ", (-key), " Tag: ", tag, !
}
// Two-level subscript: ^||Name(-score, tiebreaker) = value
// Lets you sort by score descending, then alphabetically within the same score:
Set ^||Results(-score, name) = data
Why it works: IRIS collates numeric subscripts in numeric order. Negative numbers
sort before zero, so -100 < -90 < 0. Negating the score inverts the order.
No $SortBegin / array copy / post-sort needed — the global IS the sorted structure.
Common uses: leaderboards, top-N queries, priority queues, ranked results.
npx claudepluginhub intersystems-community/iris-agentic-devWorked fix examples for 6 common ObjectScript LLM mistakes: Return vs Quit in loops, HTML escaping order, SQL date filters, list operations, postfix conditions. Uses Bug Pattern → Root Cause → Fix structure.
Provides guidance on Ruby standard library including Enumerable iteration methods, File I/O, Time/Date, Regular Expressions, and core classes. Useful for Ruby collection processing and common tasks.
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.