Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this questionIs there a way to separate open Mathematica no开发者_开发问答tebooks so that they don't share any variables? How about making it so some variables are shared but not all?
Yes, there is. I recommend reading documentation related to Mathematica contexts. In a nutshell, all variables belong to some context (namespace), and all variables can be accessed via their fully-qualified names of the form "ContextName`varName". If you just use "varName", Mathematica will search contexts in $ContextPath
(try evaluating the variable $ContextPath
to see what it is), and will use the first context where it finds that variable. In addition, each notebook specifies a context (stored in the variable $Context
) where all its variables are stored (unless fully-qualified name is used).
By default, for all notebooks the context is "Global`". Also by default, $ContextPath for all notebooks includes the "Global`" context (as well as "System`" and some others). The net result is that variables are shared across notebooks, and this can rather quickly become annoying. However, there's an easy solution. To create a "private" context for a notebook, evaluate the following:
SetOptions[EvaluationNotebook[], CellContext -> Notebook]
This notebook will be assigned a unique context (evaluate the variable $Context
to see what it is). Also, global context will be removed from ContextPath (try evaluating $ContextPath
before and after the SetOptions[...]
above to see what's going on.)
[Update: As pointed out by rcollyer on the new Mathematica stack exchange, to set this option as the default for new notebooks, do the following: open the Options Inspector (Ctrl+Shift+O), change the scope (in the dropdown on the top) from "Selection" to "Global Preferences"; on the left expand the nodes Cell Options -> Evaluation Options, and change the CellContext setting to "Notebook."]
Now, here's how to create a shared context:
Begin["SharedContext`"];
varShared1 = "Shared string";
End[];
Alternatively, you could've just typed
SharedContext`varShared1 = "Shared string";
Now you can either use the fully qualified names ("SharedContext`varShared1" will work in any notebook), or you can add the context to $ContextPath:
AppendTo[$ContextPath, "SharedContext`"]
If you do this in all notebooks, varShared1 will become visible without a fully-qualified name.
To summarize, context work a lot like many other search paths. However, there are many subtleties (for example, if a symbol has already been defined in some other context, the Begin["SharedContext`"]/End[] block might not work as you expect -- the existing context of the symbol will be used instead of SharedContext`), so I recommend a healthy dose of experimentation and perusing the docs.
I'm not really sure if this is a wise thing to do, but anyway.
Here is a schematic solution for two Notebooks. It may be generalized, but it's not straightforward.
Open two Notebooks
In each of them go to the menu (evaluation -> Notebook's default context -> Unique to this Notebook) With this, the symbols are not shared anymore.
In each Notebook enter something like
Context[]
to get the Notebook ContextNow in each Notebook enter the following code
.
Needs["Experimental`"];
SetAttributes[f, HoldFirst];
f[s_, val_] := ToExpression@StringJoin["Notebook$$17$799580`",
ToString@Unevaluated@s, "=", ToString@val];
ValueFunction[t] = f
Where the Notebook$$17$799580
is the context of THE OTHER Notebook (this should be able to be obtained "automatically", but this is a proof of concept only.
Now when you want to share a symbol enter
f[symbolToShare]
That's it.
You may share the value bidirectionally, or just in one direction, entering f[x] only in the Notebook you want as source value for x. The other Notebook will get the updated value, but it'll not update it back.
HTH!
Edit
Towards automation:
You may get all other open Notebook Contexts to update your shared symbols as:
ctxs[]:= Complement[Contexts["Notebook$$*"],
Flatten@Union[{Context[]},
StringCases[Contexts["Notebook$$*"], __ ~~ "Private" ~~ __]]]
So your f will become something like this (not tested)
f[s_, val_] := ToExpression@StringJoin[#,
ToString@Unevaluated@s, "=", ToString@val]&/@ctxs[];
To give all notebooks unique contexts open Options Inspector and set
Cell Options → Evaluation Options → Cell Context to Notebook
.
精彩评论