Control statements#
Code Example
Runnable Example in Jac and JacLib
# Control Statements
with entry {
# Break - exits loop
for i in range(10) {
if i > 3 {
break;
}
print(i);
}
# Continue - skips to next iteration
for j in range(5) {
if j == 2 {
continue;
}
print(j);
}
# Break in while loop
count = 0;
while True {
count += 1;
if count > 3 {
break;
}
print(count);
}
# Continue in while loop
n = 0;
while n < 5 {
n += 1;
if n % 2 == 0 {
continue;
}
print(n);
}
# Skip (Jac-specific, used in walker contexts)
walker SkipWalker {
can process with entry {
skip;
}
}
# Nested loops with break
for x in range(3) {
for y in range(3) {
if x == y == 1 {
break;
}
print(f"{x},{y}");
}
}
# Nested loops with continue
for a in range(3) {
for b in range(3) {
if a == b {
continue;
}
print(f"{a},{b}");
}
}
}
Jac Grammar Snippet
Description
Control Statements in Jac
Control statements alter the normal flow of execution within loops, providing mechanisms to exit early or skip iterations. Jac supports break, continue, and the walker-specific skip statement.
Control Statement Types
| Statement | Context | Scope | Effect |
|---|---|---|---|
break |
Loops (for/while) | Innermost loop | Exit loop completely |
continue |
Loops (for/while) | Current iteration | Skip to next iteration |
skip |
Walker abilities | Current node | Skip node, continue traversal |
Break Statement (Lines 4-10)
The break keyword immediately exits the innermost loop:
Lines 5-10:
- Loop starts with i from 0 to 9
- Line 6: When i > 3 (i.e., when i=4), condition is true
- Line 7: break executes, exiting the loop
- Only 0, 1, 2, 3 are printed
- Remaining iterations (4-9) never execute
Break Flow Diagram
graph TD
A[Start loop] --> B{i > 3?}
B -->|No| C[print i]
C --> D[Next iteration]
D --> B
B -->|Yes| E[break]
E --> F[Exit loop]
Continue Statement (Lines 12-18)
The continue keyword skips the rest of the current iteration and proceeds to the next:
Lines 13-18:
- Loop iterates j from 0 to 4
- Line 14: When j == 2, condition is true
- Line 15: continue skips to next iteration
- Line 17: print(j) is skipped for j=2
- Output: 0, 1, 3, 4 (2 is skipped)
Continue Flow Diagram
graph TD
A[Start iteration] --> B{j == 2?}
B -->|No| C[print j]
C --> D[End iteration]
B -->|Yes| E[continue]
E --> D
D --> F{More items?}
F -->|Yes| A
F -->|No| G[Exit loop]
Break in While Loop (Lines 20-28)
Break works the same in while loops:
Lines 21-28:
- Line 22: Infinite loop (while True)
- Line 23: Increment counter
- Line 24: When count exceeds 3, break executes
- Prints: 1, 2, 3
- Without break, this would be an infinite loop
Continue in While Loop (Lines 30-38)
Continue skips iterations in while loops:
Lines 31-38: - Line 33: Increment n first (important!) - Line 34: If n is even, skip print - Line 37: Only odd numbers are printed - Output: 1, 3, 5
Skip Statement - Walker-Specific (Lines 40-45)
Line 41-44:
- skip is used in walker contexts (not regular loops)
- Stops processing current node
- Walker continues to next queued node
- Different from break (which exits loops) and disengage (which stops the walker)
Control Statements Comparison
| Feature | break | continue | skip |
|---|---|---|---|
| Exits loop | Yes | No | N/A |
| Skips iteration | Remaining iterations | Current iteration | Current node |
| Continues loop | No | Yes | N/A |
| Walker-specific | No | No | Yes |
| Affects outer loops | No | No | No |
Nested Loops with Break (Lines 47-55)
Lines 48-55: - Nested loops: outer (x) and inner (y) - Line 50: When x=1 and y=1, break executes - Break only exits inner loop, not outer loop - When x=1, prints (1,0) then breaks; outer loop continues with x=2
Break Scope Visualization
graph TD
A[x=0] --> B[y: 0,1,2]
B --> C[x=1]
C --> D[y=0]
D --> E{x==y==1?}
E -->|No| D
E -->|Yes| F[break inner loop]
F --> G[x=2]
G --> H[y: 0,1,2]
style F fill:#c62828,stroke:#fff,color:#fff
Nested Loops with Continue (Lines 57-65)
Lines 58-65: - Line 60: When a equals b, skip that iteration - Continue only affects inner loop - Prints all pairs where a ≠ b - Output: (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)
Common Patterns
Early exit on condition:
Filter during iteration:
Bounded loop:
Skip diagonal in matrix:
Best Practices
- Use break for early termination: When you've found what you need, exit the loop
- Use continue for filtering: Skip unwanted items instead of wrapping code in if statements
- Avoid deep nesting: Multiple levels of break/continue can be confusing
- Consider alternatives: Sometimes restructuring with functions is clearer
- Document intent: Comment why you're breaking or continuing
Break vs Return
| Aspect | break | return |
|---|---|---|
| Exits loop | Yes | N/A |
| Exits function | No | Yes |
| Continues after | Yes (after loop) | No (leaves function) |
| Can return value | No | Yes |
Loop Control Limitations
- Only affects innermost loop: Cannot break/continue outer loops directly
- No labeled breaks: Jac doesn't support labeled break statements
- Function boundaries: Cannot break/continue across function calls
- Walker context: Use
skipfor walker-specific control, not break/continue
When to Use Each
Use break when:
- Search finds target
- Error condition detected
- Maximum iterations reached
- Early termination improves performance
Use continue when:
- Filtering items in a collection
- Skipping invalid data
- Processing only subset of items
- Avoiding nested if statements
Use skip when:
- Walker should skip current node
- Node doesn't meet criteria
- Avoiding duplicate processing
- Conditional graph traversal