Skip to main content
1 of 6
Mr.Wizard
  • 275.2k
  • 34
  • 606
  • 1.5k

Since, to the best of my knowledge, is not possible to program a custom interface that is integrated at the level of atomic objects such as a SparseArray I think some compromise is unavoidable.

Edmund's method is the first one that came to mind, and I voted for it. It may still be your best option.

However it is not robust in the manner I think you are seeking. Consider for example:

expr = Hold[{1, discreteData[x, y, {z1, z2, z3}], 3}]; Apply[foo, expr, {2}] Apply[foo, expr, {3}] Map[foo, expr, {3}] 
Hold[{1, foo[x, y, {z1, z2, z3}], 3}] Hold[{1, discreteData[x, y, foo[z1, z2, z3]], 3}] Hold[{1, discreteData[foo[x], foo[y], foo[{z1, z2, z3}]], 3}] 

I imagine that none of these are the result you would hope to see from each operation.

Perhaps though it would be better for these functions to ignore your construct rather than mutating it errantly.

Proposal

One compromise to achieve this is to make a separate definition for each Symbol to which a data set is assigned. To do this I shall use two utility definitions and a global variable $DD. All your UpSets should be given in the body of setDefsFor; I'll only include the one.

SetAttributes[{setDiscreteData, setDefsFor}, HoldFirst]; setDiscreteData[s_Symbol, rhs_] := (setDefsFor[s]; s = rhs); setDefsFor[s_Symbol] := With[{a := $DD[s]}, s /: Set[s, new_] := a = new; s /: Length[s] := Plus @@ (Last /@ a[["tally"]]); ] 

Now you would define a data set like this:

setDiscreteData[dd, <|"scale" -> 1.234, "bias" -> 5.678, "tally" -> {{-5, 2}, {-4, 251}, {-3, 5941}, {-2, 60383}, {-1, 241185}, {0, 383613}, {1, 241644}, {2, 61035}, {3, 5686}, {4, 259}, {5, 1}}|> ]; 

The defined rules apply:

Length[dd] 
1000000 

Every other operation sees dd as an atomic Symbol and handles it as such:

expr = Hold[{1, dd, 3}]; Apply[foo, expr, {2}] Apply[foo, expr, {3}] Map[foo, expr, {3}] 
Hold[{1, dd, 3}] Hold[{1, dd, 3}] Hold[{1, dd, 3}] 
Replace[dd, x_ :> foo, 1] dd + 8 
dd 
8 + dd 
Mr.Wizard
  • 275.2k
  • 34
  • 606
  • 1.5k