18
$\begingroup$

May be someone can explain why I can't use Begin["context`"] and End[] inside a Manipulate expression, or inside the initialization section?

When I use it in the Manipulate expression, and close the notebook and restart, I get the error:

enter image description here

Here is the code, please feel free to modify as needed. I am just trying to see if the idea of different contexts can be used inside Manipulate. It is just not seeing obj`f[] at all.

Manipulate[ Begin["obj`"]; f[y_] := y^2 + 1; End[]; {x, Date[], obj`f[1]}, {{x, 0, "x"}, 0, 10, 1, Appearance -> "Labeled"}, TrackedSymbols :> {x} ] 

I also tried in the initialization section, same problem. I think this is because Manipulate itself is a Dynamic module, it does not like new context created inside it?

This is a snapshot of the above:

DynamicModule[{x = 5}, Begin["obj`"]; f[y_] := y^2 + 1; End[]; {x, Date[], obj`f[1]} ] 

Outside Manipulate, it works fine of course: (restating kernel helps before running this below again after the above just in case)

Begin["obj`"]; f[y_] := y^2 + 1; End[]; obj`f[2] 

gives 5

$\endgroup$
1

1 Answer 1

25
$\begingroup$

Short answer: yes, it is possible.

The problem is that parsing is done line-by-line only for the top-level code. For code inside some head(s), it is first parsed as a whole. Therefore, your f is parsed to Global`f, and this is why that symbol is used. Here is what you can do, schematically:

DynamicModule[{x = 5}, With[{def = MakeBoxes[f[y_] := y^2 + 1;], ff = MakeBoxes[f]}, Block[{$ContextPath}, BeginPackage["obj`"]; ReleaseHold[MakeExpression@ff]; Begin["`Private`"]; ReleaseHold[MakeExpression@def]; End[]; EndPackage[]] ]; {x, Date[], obj`f[1]}] 

What we do here is to delay the parsing (or, more precisely, the last stage of it) of our definition until run-time, converting it first to boxes and thus preventing its premature parsing. I used a similar technique in my answer in this thread. We could have converted to strings, but I prefer boxes as being still "on this side of Mathematica".

Note that a side effect of this code is that a symbol f is still created in the context which is current when the code executes (Global` here). If you want to avoid that, you could insert Remove[f] before Block. I went all the way to use `Private` sub-context, to avoid polluting the current context with some auxiliary symbols created during assignments.

You can also automate this code with some meta-programming.

$\endgroup$
2
  • $\begingroup$ ReleaseHold[MakeExpression@ff]; can be simplified to ToExpression[ff], right? $\endgroup$ Commented May 6, 2022 at 3:14
  • $\begingroup$ @xzczd Looks like that. I can't remember now, what was the reason to use this longer form. $\endgroup$ Commented May 7, 2022 at 2:14

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.