How can I ensure that symbols passed through MathLink retain their full context information? When using MathLink naively, they do not.
Demonstration, controlling another kernel:
link = LinkLaunch["\"" <> First[$CommandLine] <> "\" -mathlink"];
LinkRead[link]; (* read initial prompt *)
foo`x; (* create symbol *)
AppendTo[$ContextPath, "foo`"]; (* add foo` to context path so now x refers to foo`x *)
Context[x] (* verify the context of x *)
(* "foo`" *)
LinkWrite[link, Unevaluated@EvaluatePacket[Context[foo`x]]] (* send foo`x to the other kernel and check its context there *)
LinkReadHeld[link]
(* Hold[ReturnPacket["Global`"]] *)
The other kernel thinks that x
has context Global`
. It must have been sent without any context information. I want it to retain its context, foo`
, while being sent over.
It's the same situation when sending symbols back through the link: they do not retain context information.
I do have a sort of a workaround: temporarily unset $ContextPath
on both sides of the link.
Block[{$ContextPath},
LinkWrite[link, Unevaluated@EvaluatePacket[Block[{$ContextPath}, (* code goes here*)]]
]
But this has obvious undesirable effects. For example, what if the code that is being sent has ToExpression
? Parsing is influenced by $ContextPath
. What if the code sets $ContextPath
? Many things will break in obscure ways. This can be made more complicated to fix some of the problems, but I am hoping for a better way.
If I do the same experiment with the parallel tools (ParallelEvaluate[..., DistributedContexts -> None]
), I see that context information is in fact preserved. So there must be a way to accomplish this.