Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mathematica - Separating Notebooks [closed]

Is there a way to separate open Mathematica notebooks so that they don't share any variables? How about making it so some variables are shared but not all?

like image 414
knpwrs Avatar asked Feb 04 '11 08:02

knpwrs


2 Answers

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.

like image 114
Leo Alekseyev Avatar answered Oct 01 '22 03:10

Leo Alekseyev


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[]; 
like image 39
Dr. belisarius Avatar answered Oct 01 '22 03:10

Dr. belisarius