*** Here's the original post...
I'm setting up a secondary kernel in sandbox mode with LinkLaunch
, and need to pass various expressions to it for evaluation. These expressions are only known at runtime, however (grabbed from notebook cells that the end-user writes). I need to wrap them in Hold
to prevent evaluation in the main kernel before they get passed off to the secondary via LinkWrite
. The problem I'm having is that somehow, ReleaseHold
is ignored when passed through LinkWrite
. Here's an example:
In[17]:= newKernel = LinkLaunch[First[$CommandLine] <> " -wstp -noicon"]
Out[17]= LinkObject["/Applications/Mathematica.app/Contents/MacOS/\ WolframKernel -wstp -noicon", 893, 7]
In[18]:= LinkWrite[newKernel, Unevaluated@EvaluatePacket[Developer`StartProtectedMode[]]]
In[19]:= LinkRead[newKernel]
Out[19]= InputNamePacket["In[1]:= "]
In[20]:= LinkRead[newKernel]
Out[20]= ReturnPacket[Null]
In[21]:= LinkWrite[newKernel, Unevaluated@EvaluatePacket[foo = 2]]
In[22]:= LinkRead[newKernel]
Out[22]= ReturnPacket[2]
In[23]:= LinkWrite[newKernel, Unevaluated@EvaluatePacket[foo^2]]
In[24]:= LinkRead[newKernel]
Out[24]= ReturnPacket[4]
In[25]:= expression = Hold[bar = 3]
Out[25]= Hold[bar = 3]
In[26]:= LinkWrite[newKernel, Unevaluated@EvaluatePacket@ReleaseHold[expression]]
In[27]:= LinkRead[newKernel]
Out[27]= ReturnPacket[Hold[bar = 3]]
In[28]:= LinkWrite[newKernel, Unevaluated@EvaluatePacket[Names[Context[] <> "*"]]]
In[29]:= LinkRead[newKernel]
Out[29]= ReturnPacket[{"expression", "foo"}]
In[30]:= LinkWrite[newKernel, Unevaluated@EvaluatePacket[bar^2]]
In[31]:= LinkRead[newKernel]
Out[31]= ReturnPacket[bar^2]
In[32]:= LinkClose[newKernel]
In the line In[26]
, just as in In[23]
, the Unevaluated
prevents the expression from being evaluated in the local kernel before it gets passed through the link by LinkWrite
. I would have expected that when the expression gets to the remote kernel and is evaluated, the ReleaseHold
will remove the Hold
and the core definition bar=3
will be evaluated, defining the symbol bar
.
That, apparently, is not what happens. As far as I can tell, the ReleaseHold
is completely ignored. Perhaps someone wiser than I in the dark arts of Mathematica delayed evaluation can explain?
And, more importantly, perhaps someone can suggest a workaround so that when I have an expression in held form, I can get it evaluated by the remote kernel?
*** UPDATE: Here's my partial answer and modified question.
Oh, my... I think I just stumbled over the explanation myself. expression
is not defined in the remote kernel, so it's just an undefined symbol. As far as the remote kernel is concerned, there's no Hold
to be released!
The reason it looks like I'm getting an unreleased Hold
back is that LinkRead
returns the unevaluated expression
, which is then evaluated here in the local kernel with the definition given above.
Which still leaves me with the problem of how to pass an expression through to the remote kernel for evaluation. All the LinkWrite
examples I've found in the documentation specify an expression explicitly in the LinkWrite
call. How can one use LinkWrite
when the expression to be evaluated must be handled programmatically, i.e., is referred to by a variable?