2

I would like to create a data structure of the type "header[pointer]" where pointer would point to a list. I will shown on an example how I'd like this to work, and where the problems are.

In[1]:= pointer = Unique[storage];
Out[1]= storage$113

So far so good. Now I want to assign some values to the storage

In[3]:= Evaluate[pointer] = {v1, v2, v3}
Out[1]={v1,v2,v3}

Evaluate is needed in order to enforce evaluation of the left hand side of the assignment. The pointer has not been touched/changed which is good:

In: Trace[pointer]
Out: {pointer, storage$113, {v1,v2,v3}}

it still points to the storage, which in turn points to the list with the actual data. Yet, now it starts evaluating to something beyond storage$113. This will turn up later as the main problem.

Now I'd like to have something like header[storage$113] as a wrapper to pass this around functions, and here the problems start. If one tries

In: header[pointer]
Out: header[{v1,v2,v3}]

the pointer evaluates down to the values. Thus we get bust since pointer evaluates way to much. If one tries

In: SetAttributes[header, HoldAll]

to prevent its evaluation one gets, alas, that it evaluates too little:

In: header[pointer]
Out: header[pointer]

I found a way

In: header[tmp] /. tmp -> Trace[pointer][[2]]
Out: header[storage$113]

that finally does the trick. I really do not understand why this works, actually. Trace[pointer][[2]] should also evaluate down to values v1, v2, ... This implementation might be problematic for several reasons: Trace might come up with a rather long list, and I just need the second element of it! Another problem, I suppose that the output of the Trace command might change dynamically depending on whether one puts in some extra definitions. I suppose that this is theoretically possible.

Another way would be to issue header[pointer] command while pointer is still unspecified as

pointer = Unique[storage];
object = header @@ {pointer}
... fix storage here...

but this forces me to do something I potentially might not want to do. For example, what if the command object = header... has to come at the end for whatever reasons?

Anyway, I feel these both constructs looks very fragile I think and I'd like to understand how to controll these things better.

Are there better ways?

Verbeia
  • 34,233
  • 9
  • 109
  • 224
zorank
  • 829
  • 4
  • 14

1 Answers1

3

In situations where you want to only evaluate a variable "one level", you can instead apply it's OwnValues so for instance when you have:

pointer=Unique[storage];
SetAttributes[header,HoldAll];
header[pointer]/.OwnValues[pointer]

(* header[storage$17156] *)

I would also recomend using extract when you need to operate on a held symbol. For instance to set the value of the above structure you could use:

Extract[header[storage$17156], 1, Function[v, v= 34, HoldAll]]

Using Extract and an anonymous function with HoldAll means the OwnValues for storage$17156 won't be applied prior to storage$17156=34 evaluates.

A potential way of making this method look nicer is to use UpValues of a custom symbol to change how SetDelayed (:=) is evaluated:

pointerValue /: SetDelayed[var_, pointerValue[value_]] /; Head@var === header :=
     Extract[var, 1, Function[v, v = value, HoldAll]]

pointerValue::whdr = 
    "Attempted to use non-pointer object: `1` as a pointer during    SetDelayed";
pointerValue /: SetDelayed[var_, pointerValue[value_]] := 
    (Message[pointerValue::whdr, Defer[var]]; $Failed)

This way you can set new values for your header object using:

myObj = header[pointer] /. OwnValues[pointer];
myObj := pointerValue[1];
myObj[[1]]
myObj := pointerValue[2];
myObj[[1]]

(*1*)
(*2*)

With the only change in syntax being that you have to specify that you are attempting to assign a value to a pointer using the pointerValue wrapper on the right hand side of SetDelayed.

Vincent
  • 131
  • 1
  • Many thanks! If not too problematic, would it be hard to explain what you mean by the setdelayed code? I think you showed something that is beyond my understanding which seems very valuable. –  Feb 05 '13 at 12:53
  • actually, I do not understad the syntax of the pointerValue /: ... command. I mean, I should, I am not a novice to Mathematica, but I do not understand it. /; is conditioning, but the := sign at the far right is very confusing. – zorank Feb 11 '13 at 20:02