I have two dynamic objects, one nested in the other. Both have their own functions defined, as follows. I have simplified them to the point where they don't make much sense, but can still illustrate my problem. When evaluated like this, it works as expected:
ClearAll[inner, outer];
inner[Dynamic[x_, args___]] := DynamicModule[{updateInner},
updateInner[] := (Print@"inner"; args@1);
Slider[Dynamic[x, (updateInner[]; x = #) &]]
];
outer[Dynamic[x_, args___]] := DynamicModule[{updateOuter},
updateOuter[] := (Print@"outer"; args@1);
{inner[Dynamic[x, (updateOuter[]; x = #) &]], Dynamic@x}
];
x = 1;
outer[Dynamic@x]
Any movement of the slider produces an "inner"
- "outer"
pair.
However, when I rename both update functions to the same update
, outer
will use the inner update
instead of its own.
ClearAll[inner, outer];
inner[Dynamic[x_, args___]] := DynamicModule[{update},
Print@{"inner:", SymbolName@update};
update[] := (Print@"inner"; args@1);
Slider[Dynamic[x, (update[]; x = #) &]]
];
outer[Dynamic[x_, args___]] := DynamicModule[{update},
Print@{"outer:", SymbolName@update};
update[] := (Print@"outer"; args@1);
{inner[Dynamic[x, (update[]; x = #) &]], Dynamic@x}
];
x = 1;
outer[Dynamic@x]
{outer:, update$337} {inner:, update$338}
This issues $RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of x=1. >>
and only "inner"
is printed, never "outer"
. Note, that the two symbol names are (inner and outer update
) not identical: update$337
and update$338
.
Of course I can always rename one update function to something else, but relying on renaming when seeking robustness is never ok. How to design GUI objects that have update functions and can be safely embedded in outer GUI objects, with function-forwarding using the second argument of Dynamic
?
Localizing update
functions with a Module
is not a good idea as the update
function might rely on dynamic variables (on my real case it does).
DynamicModule
simply adds two$
signs after the local variables. So, bothinner
andouter
usesupdate$$
for the function name. Since(x = #; update[]) &
is a pure function and is unevaluated, it simply becomes(x = #; update$$[]) &
.inner
definesupdate$$
afterouter
, so the definition set byouter
is not used. Try:Module[{x}, {x, Module[{x}, x]}]
andDynamicModule[{x}, {x, DynamicModule[{x}, x]}]
. $\endgroup$