MathGroup Archive 2009

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: How to find which variable caused the trigger in Manipulate[]

  • To: mathgroup at smc.vnet.net
  • Subject: [mg104160] Re: [mg104136] Re: How to find which variable caused the trigger in Manipulate[]
  • From: John Fultz <jfultz at wolfram.com>
  • Date: Wed, 21 Oct 2009 06:31:33 -0400 (EDT)
  • Reply-to: jfultz at wolfram.com

On Tue, 20 Oct 2009 22:13:15 -0500, Nasser M. Abbasi wrote:
>
>
> From: "John Fultz"
>
> "Now this code has the distinct advantage that it works, and it's not so
> complicated, but there's one fatal flaw in it.  It relies on the same
> undocumented assumption I discussed earlier...that Dynamics are validated
> left-to-right.  It would fall down if you flipped the order of the Row[],
> or in a hypothetical future implementation of Dynamic that violates this
> assumption. So that's not my final solution.  But I wanted you to see
> this so you could understand better how I built my final solution.  My
> final solution takes the same approach, but tracks the Dynamics as
> they're initialized, forcing the Text[] Dynamic to evaluate (possibly
> again) after the others.  The solution doesn't seem very elegant, but it
> does work.  I'm afraid that the educational value of this example will
> require some study of the code, but you seem willing to do that.  I
> reversed the Row[] in this example to prove that it does, in fact, work
> as advertised.
>
> Manipulate[Row[{
>
> Dynamic[Refresh[
> Switch[dynamicsInitialized,
> {True, True, False}, dynamicsInitialized[[3]] = True;r = initialState,
> {True, True, True}, initialState = r];
> Text[r], TrackedSymbols -> {y, x, dynamicsInitialized}]],
>
> Dynamic[Refresh[dynamicsInitialized[[1]] = True; r = x;
> "",TrackedSymbols -> {x}]],
>
> Dynamic[Refresh[dynamicsInitialized[[2]] = True; r = y;
> "",TrackedSymbols -> {y}]]}
> ],
>
> {x, 0, 1, 0.01},
> {y, 0, 1, 0.01},
> {r, "", "", ControlType -> None},
> {{initialState, 0},   ControlType ->None},
> {{dynamicsInitialized, {False, False, False}}, ControlType -> None},
>
> Initialization :>  (dynamicsInitialized = {False, False, False})
> ]
>
> "
>
> Brilliant John as always.
>
> Studying your code, I just learned something I never knew about
> Manipulate, which is probably why I could not come up with a solution.
>
> I was wondering, since in the code above, dynamicsInitialized variable is
> initialized to {False, False, False}, then, assuming does not "touch" the
> "y" slider at all the whole time, then how could the Switch statement,
> which checks only for  {True, True, False} and  {True, True, True}, ever
> gets executed?
>
> Since only when the "y" slider is moved, would you set the
> dynamicsInitialized[[2]] to true.
>
> Yet, when I look at the DynamicModule[] code generated by the hitting the
> "Paste snapshot" button in the corner of the Manipulate display, it says
> that dynamicsInitialized has the value  {True, True, True} each time !
> But how could it be so, I have not even touched the "y" slider! even if I
> do not touch the "x" slider, this variable will have this value.
>
> But when I click the "initial settings" button, then look at the "Paste
> snaphot", then I see this variable having the value {False, False,=
 False}.
>
> I came up with a theory on how this could be:
>
> Just by the act of displaying the Manipulate result on the screen, or
> scrolling over it, all the control variables will be "activated", or
> "triggered" initially, even when one has not physically moved the
> slides/the controls yet.
>
> This means there will be some initial evaluations of the Manipulate
> expression. 3 initial evaluations that occur behind the scene before I
> ever get to touch the sliders.
>
> The first evaluation detects that "x" is triggered (or maybe "y", since
> the order is not defined), so this will cause dynamicsInitialized to
> become {True, False, False}.
>
> The second evaluation will detect that "y" control variable is triggered,
> so now dynamicsInitialized becomes {True, True, False}.
>
> And now in the third evaluation, since dynamicsInitialized is being
> tracked also, and it has changed from the above evaluations, then now and
> only now, would one of the Switch statement conditions be used, the one
> which checks for {True, True, False}.and this will finally cause
> dynamicsInitialized becomes {True, True, True}. And now the rest will
> follow as the user moves the "x" or the "y" slides.
>
> Thanks again for your help John.
>
> --Nasser

Yes, you've largely got it.  For purposes of full understanding, I'll just 
correct a very forgivable oversight.

Not three evaluations, but six.

Evaluation 1: The code in Initialization comes first.  That's a documented,
ironclad guarantee.  My solution relies on that guarantee.

The remaining evaluations, as I've stressed, could hypothetically come in any 
order, but in version 7, here's how they come...

Evaluation 2: The Switch[] code.  But the Switch[] fails, as dynamicsInitialized 
will be {False, False, False}, remains unevaluated, and r is left unchanged.

Evaluation 3: The x initialization, as you say.

Evaluation 4: The y initialization, as you say.

Evaluation 5: Evaluations 3 and 4 have now re-tickled the Switch[] code, by
virtue of changing dynamicsInitialized (you'll note that I added 
dynamicsInitialized to that particular Refresh).  So now the Switch[] code 
evaluates again, but this time with dynamicsInitialized set to {True, True,
False}

Evaluation 6: Evaluation 5 now tickles *again* the Switch[] statement by virtue 
of changing dynamicsInitialized to {True, True, True}.  So one last 
re-evaluation.

And now things are in a stable state and no further evaluations happen until you 
start moving sliders.

Sincerely,
 
John Fultz
jfultz at wolfram.com
User Interface Group
Wolfram Research, Inc.




  • Prev by Date: Re: Question on Dynamic with "DockedCell"
  • Next by Date: Re: Question on Dynamic with "DockedCell"
  • Previous by thread: Re: Re: How to find which variable caused the trigger in Manipulate[]
  • Next by thread: Re: How to find which variable caused the trigger in Manipulate[]