Variable Scoping in Nested Generates¶
Moving a <variable> from an outer <generate> into a nested <generate>
changes which record owns the value. Keep that ownership visible in every
script= expression so a reviewer can tell whether the current or parent
record is intended.
Review Rules¶
- Use
this.<name>for a value declared in the current nested generate. - Use
this.parent.<name>when the direct parent owns the value. - Use an explicit named path only when the model intentionally addresses a previously built nested branch.
- Use
root.<name>for a value owned by the setup scope. - Read memstore data through the public Scripting API. Do not imitate a
memstore record with a locally constructed
dictjust to move it between scopes.
Quick Decision Guide¶
| You want to read... | Preferred form |
|---|---|
A value in the current nested <generate> |
this.varName |
A value in the direct parent <generate> |
this.parent.varName |
| A setup value | root.varName |
| An intentional named branch | child.grand_child.varName |
An unqualified name can still resolve to an outer value. That is concise at the top level, but ambiguous when the same name exists in more than one nested generate.
Example 1: Memstore Values Through the Scripting API¶
The helper keeps memstore communication behind the supported read-only API:
| script/scope_memstore.scr.py | |
|---|---|
1 2 3 4 5 | |
A parent-owned value¶
| scope-outer.xml | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
selected belongs to batch, so the nested generate reads it explicitly from
this.parent.
Current and parent values with the same name¶
| scope-shadowing.xml | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
The three expressions make their ownership reviewable: this.selected and
datFileCreation.selected read inner; this.parent.selected reads outer.
Example 2: Cascade Generate and this.id¶
| scope-cascade.xml | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
The outer id is unqualified because it is at the top level. Every nested
id uses this.id, so reusing the same name cannot hide which value is read.
Example 3: Named Path Access¶
| scope-named-path.xml | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
Use a named path when the path itself matters to the model. For a merely local
value, this.index remains easier to review.
Example 4: Explicit Paths in nestedKey¶
| scope-nested-key.xml | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
The path shows that contact deliberately reuses values owned by send_info.
Example 5: Shared Outside, Local Inside¶
| scope-shared-local.xml | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
The shared customer ID stays in the parent. Each child keeps its own local line counter and qualifies both reads.
Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
variable not found |
The value is owned by another scope | Use this.<name>, this.parent.<name>, or the intentional named path |
| Wrong value without an error | An unqualified name resolved to an outer value | Qualify current and parent ownership explicitly |
| A path breaks after nesting changes | The named branch changed | Prefer this.* for local values; reserve named paths for intentional branch access |
| Memstore logic exposes runtime objects | The model bypasses the public boundary | Move the read to datamimic_ee.scripting.load_memstore() or load_memstore_page() |