Example and background ( note the usage of Hold, ReleaseHold ):
The following code represents a static factory method to create a scenegraph object ( from an XML file ). The (output-)field is an instance of CScenegraph ( an OO-System class ).
new[imp_]:= Module[{
ret,
type = "TG",
record ={{0,0,0},"Root TG"}
},
ret = MathNew[
"CScenegraph",
2,
MathNew["CTransformationgroup",1,{type,record},0,0,0,0,Null]];
ret@setTree[ret];
ret@getRoot[]@setColref[ret];
csp = loadClass["CSphere"];
spheres = Cases[imp, XMLElement["sphere", _, __], Infinity];
codesp = Cases[spheres, XMLElement["sphere",
{"point" -> point_, "radius" -> rad_, "hue" -> hue_}, {}] -> Hold[csp@new[ToExpression[point], ToExpression[rad], ToExpression[hue]]]];
ret@addAschild[ret@getRoot[],ReleaseHold[codesp]];
ret
];
My question is about the following:
spheres = Cases[imp, XMLElement[\sphere\, _, __], Infinity];
codesp = Cases[spheres, XMLElement[\sphere\,
{\point\ -> point_, \radius\ -> rad_, \"hue\" -> hue_}, {}] -> Hold[csp@new[ToExpression[point], ToExpression[rad], ToExpression[hue]]]];
ret@addAschild[ret@getRoot[],ReleaseHold[codesp]];
where
addAschild
adds ( a list of ) geometries to a ( root ) transformationgroup and has the signature
addAsChild[parent MathObject, child MathObject], or
addAsChild[parent MathObject, Children List{MathObject, ...}]
and the XML element representing a sphere looks as follows:
<sphere point='{0., 1., 3.}'
radius='1'
hue='0.55' />
If I do NOT USE Hold[] , ReleaseHold[] I end up with objectdata like
{"GE", {"SP", {CScenegraph`point, CScenegraph`rad}}, {CScenegraph`hue}}
while I would have expected
{"GE", {"SP", {{4., 3., -4.}, 3.}}, {0.45}}
(The above code with Hold[], ReleaseHold[] yields the correct data.)
Questions
1. Why is Hold necessary in this case? ( In fact, is it? Is there a way to code this without Hold[], ReleaseHold[]? ) ( I got it right by trial and error! Don't really understand why. )
2. As a learning point: What is the prototypical example / case for the usage of Hold / ReleaseHold?
EDIT:
Summary of Leonid's answer. Change this code
codesp = Cases[spheres, XMLElement["sphere",
{"point" -> point_, "radius" -> rad_, "hue" -> hue_}, {}] -> Hold[csp@new[ToExpression[point], ToExpression[rad], ToExpression[hue]]]];
ret@addAschild[ret@getRoot[],ReleaseHold[codesp]];
to:
codesp = Cases[spheres, XMLElement["sphere",
{"point" -> point_, "radius" -> rad_, "hue" -> hue_}, {}] :> csp@new[ToExpression[point], ToExpression[rad], ToExpression[hue]]];
ret@addAschild[ret@getRoot[],codesp];