Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question

migrated from stackoverflow.com Feb 8 '13 at 15:50

This question came from our site for professional and enthusiast programmers.

    
I think I've done something very similar to what you want in this answer –  Leonid Shifrin Feb 8 '13 at 15:53
    
For pointer-like behavior, could use "expr bags" as described here. –  Daniel Lichtblau Feb 8 '13 at 16:20

1 Answer 1

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.

share|improve this answer
    
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. –  zorank Feb 5 '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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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