Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Someone know why this Button works when clicked:

testModule1[]:=DynamicModule[{button, x="",randomGrid},
    button=Button["Create table",x=RandomInteger[10,{3,3}]//MatrixForm];
    Deploy@Panel@Dynamic@Column[{button,x}]
]
testModule1[]

test1

and this not:

testModule2[]:=DynamicModule[{button, x="",randomGrid,ff},
    ff:=(x=RandomInteger[10,{3,3}]//MatrixForm);
    button=Button["Create table",ff];
    Deploy@Panel@Dynamic@Column[{button,x}]
]
testModule2[]

test2

I have some big functions to put into x, and I would like to organize my code in the second way.

share|improve this question
    
It is my understanding (correct/incorrect) that SetDelayed doesn't work inside the DynamicModule. –  Mike Honeychurch Jul 24 '13 at 22:46
3  
You can use ff[]:=... and then ff[] instead of ff inside the button code, and that will work. This does not explain however why OwnValues don't work. –  Leonid Shifrin Jul 24 '13 at 22:54
3  
Ok, here is a kind of an explanation. As @MikeHoneychurch noted, the delayed evaluation is performed in fact immediately (or at least so it looks to me too). Then, x is assigned some random matrix, and f is out of the game for the OwnValues scenario. You can look at the generated box expression in the FE for your button, to see this. However, for DownValues, while the assignment is again performed immediately, the DownValues get stored by DynamicModule with the help of DynamicModuleValues option. This keeps f[] in the button code operational. –  Leonid Shifrin Jul 24 '13 at 23:05
    
Yes!.. ff[] works, DynamicModules are very strange (or would be all MMA evaluation system?)!.. Tks @Leonid –  Murta Jul 24 '13 at 23:43
    
@Murta No problem. I agree that Dynamic can be not quite intuitive. I usually find workarounds for what I need from it, but I can't say that I have any deep understanding of it. –  Leonid Shifrin Jul 24 '13 at 23:47
show 1 more comment

4 Answers 4

Well, Mike Honeychurch and Leonid Shifrin have pretty much covered the ground, but I have one thing to add, which, while based only on observed behavior, I think helps explain what's going on.

Set and SetDelayed both create OwnValues is the form HoldPattern[symbol] :> code. The difference is that code is unevaluated in the case of SetDelayed. DynamicModule stores ownvalues as initialization assignments, symbol = value. This makes a difference because the expression value is or appears to be created by executing code. So in the case of SetDelayed, the code ends up being evaluated anyway, not when the SetDelayed is first evaluated, but when the ownvalue it creates is stored in the DynamicModule output.

One can observe this in the following

testModule3[] := 
 DynamicModule[{button, x = "", ff}, 
  ff := (Print["Boo!"]; x = RandomInteger[10, {3, 3}] // MatrixForm);
  button = Button["Create table", ff];
  Deploy@Panel@Dynamic@Column[{button, x}]]
testModule3[]
(* --> Boo! *)
(* Panel with non-working button *)

The "Boo!" is printed even though button was not pressed. If Module replaced DynamicModule, the Print statement would not have been executed and "Boo!" would not be printed.

The problem (for the designers of DynamicModule) can be seen in this:

Clear[x]

ff1 = x + 4;
x = 3;
ff2 = x + 4;
ff3 := x + 4;
OwnValues@ff1
OwnValues@ff2
OwnValues@ff3

(* {HoldPattern[ff1] :> 4 + x} *)
(* {HoldPattern[ff2] :> 7} *)
(* {HoldPattern[ff3] :> x + 4} *)

One can see that ff1 and ff3 are equivalent, even if not strictly identical. But why should this be a problem? Why not store these ownvalues in the form they are above? In that case, DynamicModule would work just like the rest of Mathematica (just like Module in Kuba's second solution). The answer I think is fairly simple, but for me it is just a guess: speed. Just as Compile is limited to a simpler subset of functionality, so is dynamic interactivity and what the front end can handle.

The kind of assignment the front end can do without communicating with the kernel is probably just a simple assignment (such as in C, say). It does not create a pattern but stores a value in the front end. Primarily I think the developers have in mind number assignments, but clearly any expression is allowed on the RHS. This allows such things as Animators to be efficient, for instance. In the case of complicated RHS expressions, the front end asks the kernel to evaluate it and send the value back. Efficiency in this sort of end-use case and minimizing computational overhead is clearly part of the design of the Dynamic system.

That's how the basic principles seem to me. That they are part of the design can be inferred from this, and the following section in Advanced Dynamic Functionality. The motivations I have guessed at may be off, and there may be further internal considerations that are yet hidden from me.


P.S. Here's another variation to solve the OP's problem, which is consistent with the explanation above: Use Hold and ReleaseHold to mimic the behavior of SetDelayed. Whether Set or SetDelayed is used to define ff does not matter. The "value" of ff in either case is the held expression, which is what is stored in the output cell (and can seen via Cell > Show Expression).

testModule4[] := DynamicModule[{button, x = "", ff},
  ff := Hold@(x = RandomInteger[10, {3, 3}] // MatrixForm);
  button = Button["Create table", ReleaseHold@ff];
  Deploy@Panel@Dynamic@Column[{button, x}]]
share|improve this answer
    
Tks Michael. Very elucidative explanation. –  Murta Jul 25 '13 at 5:46
    
+1, especially for the workaround/solution. If this is done for reasons of speed, I guess I dislike this choice. –  Jacob Akkerboom Jul 25 '13 at 10:50
1  
@JacobAkkerboom Thanks. I added a reference supporting the speed hypothesis. I would like it better if the references for Set, SetDelayed, and/or DynamicModule mentioned this limitation. –  Michael E2 Jul 25 '13 at 13:21
add comment

There are many issues arasing while creating complex DynamicModules. Usually I'm not even sure what to ask about.

This is how I would do this in order to avoid putting procedures inside Button:

    testModule2[] := DynamicModule[{randomGrid, x = "", button},
                            button = Button["Create table", ff];
                            Deploy@Panel@Column[{button, Dynamic@x}]
                            , Initialization :> (

                                ff := (x = RandomInteger[10, {3, 3}] // MatrixForm);

                                                 )

                                  ]

The less content wrapped with Dynamic, the better.

Of course it is not an answer to your question. I think Mike Honeychurch is right but I miss some kind of tutorial "how to make efficient use of scoping constructs and Dynamic for CDF creating".

Why do I think it is important?, because good luck with only DynamicModule and minimal content wrapped with Dynamic if you want to scope all names. Notice, that in above code ff is not scoped. If you need this I recommend adding Module.

  testModule2[] := Module[{ff},  
                       DynamicModule[{randomGrid, x = "", button},
                        button = Button["Create table", ff];
                        Deploy@Panel@Column[{button, Dynamic@x}]
                       , Initialization :> (     
                          ff := (x = RandomInteger[10, {3, 3}] // MatrixForm);
                        )]]

Leonid Shifrin's observation about DownValues and OwnValues is striking. It is good to know that. It can help you make such code with only DynamicModule, however I like to have main structure of the CDF on top while procedures etc. at the end. The code is more transparent then, at least IMO.

share|improve this answer
    
what does randomGrid refer or relate to? It is not in the expressions and code works without it. –  ubpdqn Jul 25 '13 at 1:25
    
@ubpdqn it is from the question code :) –  Kuba Jul 25 '13 at 4:47
    
+1, using Initialization is in my opinion the most natural solution. –  Jacob Akkerboom Jul 25 '13 at 11:08
    
@JacobAkkerboom New note. scoping ff inside DynamicModule is possible, we just have to create DownValues instead OwnValues: ff[]:= .... Not sure why though –  Kuba Feb 20 at 12:37
add comment

Unless I am mistaken (which is entirely possible) I recall reading somewhere that SetDelayed is treated as Set within DynamicModule.

When I take your second block of code and use Module instead of DynamicModule it seems to work as you want (but x etc are now kernel variables of course).

share|improve this answer
    
This toy code is a small part of a CDF file. So I need the Dynamic part. The ff[] Leonid solution works nice tks! –  Murta Jul 24 '13 at 23:44
add comment

Here is more crazyness. I think Michael explains quite well what happens. The only thing new this first section shows is that new symbols get created sometimes, which makes it seem functions point to the wrong thing, but that actually does not matter.

DynamicModule[{button, x = 0, ff, `},
 ff := (++x);
 var = Hold[x];
 var2= z;
 button = Button["setX", ff];
 Dynamic[Column@{button, x, Hold[x], Hold[x], var, OwnValues[ff], z, var2}]
 ]
Hold[FE`x$$213]

Hold[FE`x$$213]

Hold[x$314]

{HoldPattern[FE`ff$$213] :> 1}

FE`z$$225

z$1236

Conclusions: It is possible for a variable to point to the wrong thing, like with var, or var2. ff does point to right thing, but it's code gets evaluated. Probably: The pointing to the wrong thing is not caused by the DynamicModule changing it's x all the time. I suppose it really wants to evaluate the code attached to symbols and not have it refer to any of the used symbols.

DownValues

Also note

DynamicModule[{gg = 0, x},
 OwnValues[gg] = {HoldPattern[gg] :> x};
 Dynamic[{OwnValues[gg], Hold[x]}]
 ]
 {{HoldPattern[FE`gg$$270]:>FE'x$$270},Hold[FE`x$$270]}

but

DynamicModule[{gg = 0, x = 0},
 OwnValues[gg] = {HoldPattern[gg] :> x};
 Dynamic[{OwnValues[gg], Hold[x]}]
 ]
 {{HoldPattern[FE`gg$$271]:>0},Hold[FE`x$$271]}

It seems it does not matter if we set something using OwnValues or in the regular way, using Set or SetDelayed. It seems that a function definition can even be changed afterwards, like in

DynamicModule[{gg = 0, x},
 OwnValues[gg] = {HoldPattern[gg] :> x};
 x = 0;
 Dynamic[{OwnValues[gg], Hold[x]}]
 ]
{{HoldPattern[FE`gg$$312]:>0},Hold[FE`x$$312]}

Order of evaluation

The order of evaluation seems only to depend on the order in which they appear in the list of local symbols in the first argument of DynamicModule.

DynamicModule[{gg, x},
 x := (Print["x"]; {2});
 gg := (Print["gg"]; First@HoldComplete[x]; Print["ggDone"]);
 ]
gg (*print*)

x (*print*)

ggDone (*print*)

x (*print*)

Null

and

DynamicModule[{gg, x},
 x := (Print["x"]; {2});
 gg := (Print["gg"]; First@HoldComplete[x]; Print["ggDone"]);
 ]
x (*print*)

gg (*print*)

x (*print*)

ggDone (*print*)

Null (*print*)

We also see that it uses the "old" definitions of symbols to generate the definitions of the new symbols. I suppose it never does use a new definition in the definition of another new symbol.

I am lost :). I don't think I like this much.

share|improve this answer
    
@Kuba again, thanks for editing :). I really like the solution of the code blocks inside the "orangy blocks" :). Now the variables with a Context (and backtick) in front of them display beautifully. I'll see how you did it. –  Jacob Akkerboom Jul 26 '13 at 10:29
    
You are welcome :) ">"+ 5 " " –  Kuba Jul 26 '13 at 10:33
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.