开发者

Mathematica - Separating Notebooks [closed]

开发者 https://www.devze.com 2023-02-09 01:47 出处:网络
Closed. This question is off-topic. It is not currently accepting answers. Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed. This question is off-topic. It is not currently accepting answers.

Want to improve this question? Update the question so it's on-topic for Stack Overflow.

Closed 10 years ago.

Improve this question

Is 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.

  1. Open two Notebooks

  2. 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.

  3. In each Notebook enter something like Context[] to get the Notebook Context

  4. Now 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 OptionsEvaluation OptionsCell Context to Notebook.

0

精彩评论

暂无评论...
验证码 换一张
取 消