Working with DynamicModule: SetDelayed + OwnValues

13

5

Shortly, definitions in form of e.g. x:= RandomReal[] have to be avoided inside DynamicModule[{x}, ...]. Why?, this Prints immediately:

DynamicModule[{x}, x := Print[1]; {}]

It hit us hard in the past, e.g.:

So what is the official rule here?

ref / DynamicModule / Details and Options / (-4)th bullet point

Ordinary values of symbols are saved in the first argument of the DynamicModule; other values are saved in the setting for the DynamicModuleValues option.

This is almost useless since "Ordinary values of symbols" and "other values" have no real meaning in Mathematica.

J. Fultz in ShearingTransform and Dynamic:

An issue which is causing confusion among the commenters is that DynamicModule, sadly, does not support SetDelayed on its member variables. SetDelayed is silently translated to Set.

Closer but not quite there yet, x[]:=RandomReal[] will work well.


Kuba

Posted 2016-07-27T08:17:31.570

Reputation: 129 207

2really intriguing and helpful! – Wjx – 2016-07-27T08:43:29.960

Answers

15

J. Fultz' answer indicates that it is not a but a which needs better documentation.

Get a habit of defining your procedures with [], e.g. f[]:=Print[1]. (Which creates DownValues instead of OwnValues).

DynamicModule saves its variables' OwnValues in the first argument of that DynamicModule. Which does not support SetDelayed and is sliently translated to Set. (e.g. DynamicModule[{x := RandomReal[]}, {}] is left unevaluated)

Values other than OwnValues will be saved in DynamicModuleValues option and work as expected.

"Proof"

InputForm @ DynamicModule[{x}, x[] := RandomReal[]; {}]
DynamicModule[{x}, 
    {}, 
    DynamicModuleValues :> {{DownValues[x] = {HoldPattern[x[]] :> RandomReal[]}}}
]
 InputForm @ DynamicModule[{x}, x := RandomReal[]; {}]
DynamicModule[{x = 0.20406205529616095}, 
    {}, 
    DynamicModuleValues :> {}
]

I've already sent a report with a request to improve DynamicModule's documentation:

A support case with the identification [CASE:3676288] was created.

[...] I have filed a suggestion with the appropriate development team requesting that we better document how DynamicModule handles SetDelayed OwnValues. [...]

Kuba

Posted 2016-07-27T08:17:31.570

Reputation: 129 207

2As I was reading the question I wondered why I had not personally been bitten by this that I could recall, but seeing this answer I realize that I already use the form f[] the vast majority of the time, inside or outside of DynamicModule. I have for years felt that this is superior in general as it allows passing Symbol names without unexpected evaluation, and because to me it better follows the apparent paradigm of the language. I personally quite dislike the exceptions such as Quit that have action as bare Symbols. IMHO f[] should be the guideline everywhere. – Mr.Wizard – 2016-07-27T16:35:21.210

A post related to my thoughts above: (32202)

– Mr.Wizard – 2016-07-27T17:11:59.313

@Mr.Wizard Yep, this also helps with accidental reloading (Get) of packages. Where otherwise delayed OwnValues could destructively interfere. – Kuba – 2016-07-27T19:59:06.683