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).
DynamicModulesimply adds two$signs after the local variables. So, bothinnerandouterusesupdate$$for the function name. Since(x = #; update[]) &is a pure function and is unevaluated, it simply becomes(x = #; update$$[]) &.innerdefinesupdate$$afterouter, so the definition set byouteris not used. Try:Module[{x}, {x, Module[{x}, x]}]andDynamicModule[{x}, {x, DynamicModule[{x}, x]}]. – JungHwan Min May 28 '16 at 18:18{Dynamic@inner[Dynamic[x, (x = #; update[]) &]], Dynamic@x}in the definition ofouter, it still goes to an inifnite recursion. – István Zachar May 29 '16 at 10:47