JHM is right about the reason. John Fultz shows nice versioning and coding style I'm encouraging to use. Yet there is no answer to how to avoid this problem in general and flexible way.
Here is my attempt, I will skip JF enhancement to not complicate things but it can be used with this method too.
The problem is that whatever symbol name we use it may happen that the collision will occur as soon as our name will already be somewhere on $ContexPath
(at a time of parsing those two controllers). It would be nice to don't have to come up with unique symbols which are not readable and handy, for every piece of code we write.
The solution is to ensure that the context in which update
is parsed will be unique.
We can achieve this sticking to two rules:
- each "modular" gui element should be defined in own "subcontext"
each "modular" gui element should be defined in own "subcontext"
So e.g. between
Begin["`inner`"]/End[]
So e.g. between Begin["`inner`"]/End[]
DynamicModule
variables should be typed with a backtick`update
so that we are sure that even whenupdate
is somewhere in$ContexPath
"our"update
will be`inner`update
.DynamicModule
variables should be typed with a backtick`update
so that we are sure that even whenupdate
is somewhere in$ContexPath
"our"update
will be`inner`update
.
Here is a minimal example of such package:
ClearAll["GUI`*"];
BeginPackage["GUI`"];
inner; outer;
update (*it isn't part of the solution, it is here to simulate \
"update" being on context path*)
Begin["`Private`"];
Begin["`inner`"];
inner[Dynamic[x_, args___]] :=
DynamicModule[{`update}, Print@{"inner:", SymbolName@`update};
`update[] := (Print@"inner"; args@1);
Slider[Dynamic[x, (`update[]; x = #) &]]];
End[];
Begin["`outer`"];
outer[Dynamic[x_, args___]] :=
DynamicModule[{`update}, Print@{"outer:", SymbolName@`update};
`update[] := (Print@"outer"; args@1);
{inner[Dynamic[x, (`update[]; x = #) &]], Dynamic@x}];
End[];
End[];
EndPackage[];
Now, since we have GUI`Private`inner`update
and GUI`Private`outer`update
there is no collision. Which was achieved with minimal effort and works even when GUI`update
is on $Path
during parsing.
x = 1;
outer[Dynamic@x]
Prints inner/outer