# Unintentional function memoisation via Dynamic

I needed to display edge labels of a graph in a way that allows the edge labels to be moved.

With[
{coords = {{1.08, 0.94}, {1.08, 0.036}, {0., 0.97}, {0., 0.}, {1.94, 0.49}},
edges = {{1, 2}, {1, 3}, {2, 5}, {3, 4}, {4, 2}, {5, 1}}},
DynamicModule[
{edgePosns = Table[0.5, {Length@edges}]},
(betweenPnt[a_, b_, l_] := (1 - l) a + l b;
DynamicModule[
{edgeCentres =
With[{av = coords[[#1[[1]]]], bv = coords[[#1[[2]]]]},
Dynamic[betweenPnt[av, bv, #2]]] &,
{edges, edgePosns}]},
Column@{
Graphics[
GraphicsComplex[
coords,
{{Line[edges]}, {Darker@Red, PointSize[0.02],
Map[Point, Range[5]]},
Map[Locator, edgeCentres]}], ImageSize -> 400],
Dynamic[DownValues[betweenPnt]]}])]]


What puzzled me is that calls to betweenPnt are memoised when the Locator-s are moved, as shown in the next image (apologies for tiny fonts):

What I do not understand is how or if the cacheing and the locator positions are connected, though I've understood from the related question that it is standard behaviour that the latter persist even when graphic is deleted and the code is re-evaluated.

Incidentally, I noticed that the DownValues are not updated dynamically despite the Dynamic wrapper around them; only after re-evaluating the whole expression do these changes appear.

-

The behavior you describe is the normal behavior for expressions displayed dynamically. For example, if you create a 3D graphics object, evaluate it, rotate the object in the output image with the mouse, and delete the output, when you re-evaluate the 3D graphic, the new output image appears in the rotated position of the deleted image. To clarify the point, the behavior is not a property peculiar to locators, but applies to all dynamic graphics.

The memoization, as you call it, isn't unintended -- it's part of the way Dynamic works. You have simply discovered some of the critters that live under the rock of Dynamic. You can't avoid this behavior.

-
yes, thanks, I get now that the locator positions are stored (as front-end variables, I suppose?): somehow I had come to believe that Dynamic values had a physical position which should get deleted if output is deleted and I didn't take account of the convenient fact that e.g. viewpoints of a deleted graphic are preserved. But I also wanted to understand why down values of a global function betweenPnt were being memoised at the same time; it was not obvious to me that they would be affected in this way. –  fairflow Apr 16 '14 at 16:50

Your code creates the following Locators, as stored in the Front End in its box form:

{LocatorBox[
Dynamic[$CellContextbetweenPnt[{1.08, 0.94}, {1.08, 0.036}, 0.5]]], LocatorBox[ Dynamic[$CellContextbetweenPnt[{1.08, 0.94}, {0., 0.97}, 0.5]]],
LocatorBox[
Dynamic[$CellContextbetweenPnt[{1.08, 0.036}, {1.94, 0.49}, 0.5]]], LocatorBox[ Dynamic[$CellContextbetweenPnt[{0., 0.97}, {0., 0.}, 0.5]]],
LocatorBox[
Dynamic[$CellContextbetweenPnt[{0., 0.}, {1.08, 0.036}, 0.5]]], LocatorBox[ Dynamic[$CellContextbetweenPnt[{1.94, 0.49}, {1.08, 0.94}, 0.5]]]}


Note the expressions that are updated when each locator is moved is betweenPnt[{1.08, 0.94}, {1.08, 0.036}, 0.5] etc. The default action is to set each expression equal to the coordinates of the position of the locator when the locator is moved. That is like memoizing it.

As for the incidental non-update of betweenPnt, the symbol betweenPnt does not itself change value, only its down values.

-
thanks @Michael E2 for the explanation, and I'm sorry to be slow, but even if betweenPnt doesn't change value, why does Dynamic[DownValues[betweenPnt]] not get updated if its down values change? –  fairflow Apr 16 '14 at 16:41