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$
    – xzczd
    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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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