2
$\begingroup$

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?

$\endgroup$
2
  • $\begingroup$ I think I've done something very similar to what you want in this answer $\endgroup$ Commented Feb 8, 2013 at 15:53
  • $\begingroup$ For pointer-like behavior, could use "expr bags" as described here. $\endgroup$ Commented Feb 8, 2013 at 16:20

1 Answer 1

3
$\begingroup$

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.

$\endgroup$
2
  • $\begingroup$ 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. $\endgroup$
    – zorank
    Commented Feb 5, 2013 at 12:53
  • $\begingroup$ 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. $\endgroup$
    – zorank
    Commented Feb 11, 2013 at 20:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.