# Why does a variable become real when using the second argument of Dynamic?

Version 9, on Windows 7.

Please compare these 2 very simple examples

Manipulate[
x,
Row[{Manipulator[Dynamic[x], {0, 10, 1/100}]}],
{{x, 1}, None}
]


and

Manipulate[
x,
Row[{Manipulator[Dynamic[x, (x = #) &], {0, 10, 1/100}]}],
{{x, 1}, None}
]


Would you not expect them to work the same way?

But in the second case, x becomes real, while in the first case it remains rational as expected. Any one knows the reasoning for this? I read about the second argument of Dynamic, but do not see something obvious. I did not read everything about it. But the above behaviour is surprising.

The fix is easy:

Manipulate[
x,
Row[{Manipulator[
Dynamic[x, (x = Rationalize[#]) &], {0, 10, 1/100}]}],
{{x, 1}, None}
]


• Particularly odd that the documentation says *Dynamic[expr] is equivalent to Dynamic[expr,(expr=#)&]. * – ssch Dec 13 '12 at 19:34
• Weeeeeeeeeeeird – Rojo Dec 13 '12 at 19:38
• Confirmed in version 7 as well. – Mr.Wizard Dec 13 '12 at 20:01
• Confirmed. It can be reproduced with the simpler Slider[Dynamic[x, (x = #) &], {0, 1, 1/10}]. I am just guessing that this has to do with the variable being handled by the front end (not kernel), which might not be able to do computations with rationals. This is a wild guess and I have no idea why the effect would show in this particular example. – Szabolcs Dec 13 '12 at 21:05
• Same with V8 on Mac – Mike Honeychurch Dec 13 '12 at 22:29

This is not an answer but it's too long for a comment. Also please remember that all the following are just guesses.

My first observation is that the simplified

Slider[Dynamic[x, (x=#)&], {0, 1, 1/10}]


can reproduce the problem.

We know that some variables (in particular DynamicModule variables) are owned by the Front End, not the Kernel, and can be directly set using GUI elements (such as Slider) without needing any kernel interaction. It is reasonable to assume that the Front End is only able to do computations with machine level data types like integers and reals, but not arbitrary precision numbers or Rationals. Why this might have an effect in this particular example, I do not know.

But let us take a look at what sort of box forms (which are handled by the front end) are generated for different variations of Slider:

1. First, the basic Dynamic with a Real step size:

Slider[Dynamic[x], {0, 1, 0.1}]

Cell[BoxData[
SliderBox[Dynamic[$CellContextx], {0, 1, 0.1}]], "Output"]  This is a simple box form that maps to the input expression directly. 2. Now let's try a Rational step size: Slider[Dynamic[x], {0, 1, 1/10}] Cell[BoxData[ SliderBox[Dynamic[ BoxFormRemapVariable[$CellContextx, {0, 1, Rational[1, 10]}],
BoxFormRemapValue[#, $CellContextx, {0, 1, Rational[1, 10]}]& ], {0, 10, 1}]], "Output" ]  Here I see something new (and to me unfamiliar): RemapValue and RemapVariable. Is this maybe used to ask the kernel to do computations? The slider range and step size are now all integers and are remapped using a (possibly kernel evaluated function) to rationals. 3. Let's try Dynamic with a second argument and a Rational step size: Slider[Dynamic[x, (x = #) &], {0, 1, 1/10}] Cell[BoxData[ SliderBox[Dynamic[$CellContextx, (\$CellContextx = #)& ], {0, 1, Rational[1, 10]}]],
"Output"]


The RemapValue is gone now!

Can we add the second argument of Dynamic back to the RemapValue version of the box form? Note that Dynamic already has two arguments there, so it should be grafted onto the RemapValue function somehow.

• It seems to me like you're right. The FE doesn't like to deal with rationals, so it turns them to reals. But in the "single agrument dynamic" case, it deals with it by changing the values of the slider to integers, and then fixing it all by tweaking the dynamic it generates. It creates a dynamic with a second argument that maps the integers to the corresponding rational, an a first argument that tells the front end to actually display the corresponding integer in the slider – Rojo Dec 14 '12 at 1:49
• They probably couldn't or didn't take the time to make a "fix" for the case at hand, when you supply your own second argument to Dynamic, that should be "mixed" with the one they generate automatically... Just more guesses – Rojo Dec 14 '12 at 1:50
• @Rojo I'm wondering why they need two transformations: RemapVariable and RemapValue. I think it has to do with how x is set based on the slider and what the slider displays based on x, but experimenting too much breaks the slider permanently sometimes. – Szabolcs Dec 14 '12 at 2:04
• I think the same. Say the range is {0, 1, 1/10}. The created slider actually goes from {0, 10} through the integers. It has to save the value/10 in the variable, and it has to display the variable*10 in the "stretched" slider – Rojo Dec 14 '12 at 2:19
• FYI you can Spelunk the definitions of BoxFormRemapVariable and BoxFormRemapValue`, they are indeed kernel functions which do just what you guessed. – Simon Woods Mar 12 '14 at 20:59