One property of Dynamic
is that its result has to be displayed and manipulated onscreen for the dynamic updating to take place. What's the best way to dynamically update "hidden" variables that nonetheless depend on and influence onscreen features (which in my case would consist of graphics and controls)?
To be more specific, I'm trying to track some symbol(s) for updates (sort of like Refresh
does—or, even better, track a function value on a symbol, e.g. only track x[[3]]
), and when the tracked symbol is updated, evaluate a certain expression (usually an assignment)—and have this all running completely in the background of some Dynamic
or DynamicModule
process.
Where to evaluate the "hidden" expression
One way seems to be to make a compound expression, and wrap the whole thing in dynamic, e.g.
Dynamic[a=f[x]; <...>; interactiveGraphicMaker[x]]
.Another seems to be to hide the update in the evaluation function, e.g.
Dynamic[interactiveGraphicMaker[x],(a=f[x]; <...>; x=g[#])&]
It also seems like I can put a
DynamicWrapper
around dynamic content, e.g.DynamicWrapper[Dynamic[interactiveGraphic[x]], Dynamic[a=f[x]; <...>]]
I also could hide the work of updating itself in my function(s), e.g. expanding
interactiveGraphicMaker[x]
intointeractiveGraphicMaker[x, hiddenvar1, hiddenvar2, ...]
all enclosed in aDynamicModule
, but I'm worried this would demand re-evaluation of the whole graphics object each time one of them changed, and slow down the computation ofinteractiveGraphicMaker
, as we'd be waiting for all of these update-checks to finish first. If all these tools exist to track symbols, why would I want to evaluate a bunch of conditionals to see if parts of x have changed before evaluating the hidden expressions? It intuitively seems better to do this kind of updating "separately". But maybe this is low-cost, or can be combined effectively with the other options, and I just don't know enough about what's happening to see that!I've seen this question and this question, which suggest setting the
FrontEndDynamicExpression
option (or using scheduled evaluation, which I don't want to do). And then I suppose I'd set up a dynamic wormhole? But if this is even a good design for performing these background updates (which I don't know), the documentation mentions that
the tricky part in setting up such a wormhole is getting the
NotebookInterfaceObject
necessary to refer to the parentDynamicModule
[...] By using DynamicModuleParent explicitly, it is possible to link up an arbitrary existing DynamicModule, but doing so is tricky, and beyond the scope of this document.
I'm not sure how I would do that, or if a value for FrontEndDynamicExpression
would even be accessible as a NotebookInterfaceObject
(or which way the "parent" link should even go!). (DynamicModuleParent
and NotebookInterfaceObject
seem to be undocumented.)
Is one of these options better than the others? Or is there an altogether better way I don't know about?
How to track updates
Another issue with tracking updates is that Refresh
used with TrackedSymbols :>
(as opposed to TrackedSymbols ->
) only works if the following symbols are actually evaluated in the first argument of Refresh
. But the documentation recommends against using ->
, as the following symbols might get evaluated under some circumstances (but doesn't say what those circumstances are). As a subquestion of "how best to perform update-controlled background assignments", since I'm guessing Refresh
will come into play: is it better to just insert an evaluation of the symbol before evaluating the first argument, e.g. Refresh[x; <...>, TrackedSymbols :> {x}]
, or to try to use Refresh[<...>, TrackedSymbols -> {x}]
and hope for the best?
Further, I'd often like to evaluate only certain assignments depending on what exactly was modified—but often these things I'd like to track are parts of my dynamic expressions, not the entire expression. E.g., I'd like to track only the value of x[[3]]
. I could imagine doing this a couple of ways:
setting up new "indicator" variables that store e.g. the value of
x[[3]]
by itself, e.g.y=x[[3]]
, and update wheneverx
as a whole does; then separately tracky
to perform the nontrivial evaluation contenthiding the nontrivial evaluation content inside a refreshed conditional which tests for updates somehow, e.g.
Refresh[If[y==x[[3]], y=x; a=f[x]; <...>], ...]
which is refreshed every timex
as a whole updates; the only difference here is that there's only oneRefresh
in play instead of two separate-but-linked ones.putting the work of updating the indicator variables into my functions, e.g. making the function that updates
x[[3]]
also set the value of the indicator variabley
(and having this be the only influence ony
)
or something else I haven't thought of.
If anyone has any advice or insight on best practices in performing these kinds of update-controlled background evaluations in a dynamic environment, I'd appreciate it!