I'm trying to set up a bunch of 2D points using UpSet
that I am going to use later for building lines and graphs.
Clear[coords, point]
coords[point[0]] = {3, 2.3};
coords[point[1]] = {8, 3.43};
etc. Also, I'm using the same approach to set up some basic characteristics for my shapes, eg. their color, PointSize
etc.
Clear[color, size]
(* colors *)
color[point[0]] ^= Blend[{Yellow, Magenta}, 0.25];
color[point[1]] ^= Blend[{Cyan, Yellow}, 0.75];
(* sizes *)
size[point[0]] ^= PointSize[0.025];
size[point[1]] ^= PointSize[0.035];
Now, I figured it would be easier to automate some part of the process eg. for making points, again using UpSet
(* make points *)
point /* ({#, size[#], color[#], Point[coords[#]]} &) /*
(Through[{First /* graphics, Rest /* Graphics}[#]] &) /*
Apply[UpSet] /@ Range[0, 1]
but it's not working how I was expecting it to behave: every time I re-evaluate the code snippet that creates my points (ie. the code shown above), I get an UpSet::write
error.
From what I gather, the first time that the code executes, it performs the expected assignments, ie it usesgraphic[point[n]]
to assign to the UpValues
of point
the associated Graphics
object, but from there on, any future evaluation prematurely (for my purposes) evaluates the part inside ... Through[{First /* graphics, ...}] ...
and when it's time for ... Apply[UpSet] ...
to do the job, it fails because it's not seeing
graphics[point[...]] ^= {graphics primitives...}
but it actually gets
Graphics[{...}] ^= {graphics primitives}
and since the contents of Graphics
are inside a List
, the kernel complains with the UpSet::write
that "Tag List in <it actually displays a graphic> is Protected", letting me know I don't have access to the UpValues
of List
, which makes sense, but I wasn't trying to do that!
My first instinct was to try and clear the definitions of graphics[point[n]]
before every new assignment, but I couldn't and this is when I realized I was having a problem of premature evaluation on my hands.
My ugly solution is to clear the definitions before re-evaluation using the following helper function unset
, which removes the relevant definitions from UpValues
before I re-insert them, using the code in the code snippet (* make points *)
above:
Clear[unset]
SetAttributes[unset, HoldFirst]
unset[head_[expr_[n_]]] := Module[{upvalues},
upvalues = UpValues[expr];
UpValues[expr] = {};
UpValues[expr] = Cases[upvalues, Except[_[head[expr[n]]] :> _]];
]
point /* graphics /* unset /@ Range[0, 1]
Is there a better approach?