87
$\begingroup$

I often correct homework by checking the calculations in Mathematica. Sometimes you would like to have two solutions open at once. However often defined symbols such as f or phi regularly overlap between the two notebooks.

  • Is there a way to separate them other than using different symbols in every notebook?

  • Is it possible to separate some variables yet share others between notebooks?

$\endgroup$
5
  • $\begingroup$ support.wolfram.com/kb/3664 $\endgroup$
    – Searke
    Commented Mar 23, 2012 at 18:22
  • $\begingroup$ @LeonidShifrin If I have two Mathematica workbooks that I would like to combine, is there a way to check whether they have any variables in common? Just like niklasfi, I often use symbols such as f in several documents. I was thinking of checking all the user-defined variables/functions in each of the documents, but I'm not sure how to do so. $\endgroup$ Commented Mar 26, 2013 at 5:20
  • $\begingroup$ @VincentTjeng As far as I know, there is no automatic way. But it is possible to write a program that would do that. You can post this as a separate question, and I am sure you will get some good answers. $\endgroup$ Commented Mar 26, 2013 at 10:36
  • $\begingroup$ This is a comment about this problem because I have run into it and been confused by it many times. I think the Mathematica staff has the responsibility to warn its purchasers about this. I also think that the default setting for any notebook should be context "unique to this notebook". $\endgroup$ Commented Oct 28, 2018 at 0:37
  • $\begingroup$ Related: mathematica.stackexchange.com/a/170711/1871 $\endgroup$
    – xzczd
    Commented Nov 22 at 12:23

3 Answers 3

106
$\begingroup$

May be this, I have not tried it, but it sounds like this is what you are looking for (if I understood you correctly):

Evaluation menu -> Notebook's Default Context -> Unique to This Notebook.

So, you do the above for each notebook.

I found this in the daily Mathematica tip webpage: http://twitter.com/mathematicatip

Update

If you want to do it programatically from within a notebook, run SetOptions[EvaluationNotebook[], CellContext -> Notebook].

Update 2

To set this automatically for all new notebooks, open the Options Inspector (Ctrl/Command+Shift+O), and change the scope to "Global Preferences." Then, the option CellContext is found under Cell Options -> Evaluation Options. Change it to "Notebook."

$\endgroup$
7
  • 1
    $\begingroup$ Is there a way to do this from within a notebook? e.g. calling a function like Quit? $\endgroup$
    – niklasfi
    Commented Jan 28, 2012 at 12:18
  • 3
    $\begingroup$ Is there a way to get Mathematica to set the context of new notebooks to be private by default, instead of having to create a private context for every new notebook manually? $\endgroup$
    – Joe
    Commented Mar 6, 2012 at 7:40
  • 2
    $\begingroup$ @Joe Just looking for that myself. I added the info to the answer. $\endgroup$
    – rcollyer
    Commented Mar 23, 2012 at 17:29
  • 1
    $\begingroup$ Yes! Thank you @rcollyer, I've been looking for a way to do this for ages! $\endgroup$
    – Joe
    Commented Mar 24, 2012 at 9:21
  • 1
    $\begingroup$ @ShutaoTang I do not know. But if you ask at Mathworks Answers forum or at comp.soft-sys.matlab someone there should know. $\endgroup$
    – Nasser
    Commented May 20, 2015 at 8:00
58
$\begingroup$

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.

$\endgroup$
4
  • 6
    $\begingroup$ You can also set this via the Evaluation > Notebook's Default Context menu (instead of SetOptions.) [The documentation uses the "Unique to Each Cell Group" setting so that there aren't any variable conflicts.] $\endgroup$ Commented Feb 4, 2011 at 14:56
  • 2
    $\begingroup$ Followup question: is there anyway to make Mathematica set the context of new notebooks to be private by default, instead of having to create a private context for every new notebook manually? $\endgroup$
    – Joe
    Commented Aug 29, 2011 at 7:16
  • 2
    $\begingroup$ @Joe: Not that I know of, but I have written some convenience functions to easily set and access private contexts. I just type setPrivate[] when I start a new notebook, and spawnScratch[] when I want to duplicate the existing notebook's context in another notebook. I've used this for over a year and found it to be acceptably convenient. The code is here: github.com/leoalekseyev/mma-context $\endgroup$
    – Leo Alekseyev
    Commented Jan 11, 2012 at 23:10
  • $\begingroup$ This is the right solution, but I strongly urge you not to change anything in the environment using the menu keys. Everything should be self contained in the notebook. As someone who has gone through several different major revisions of Mathematica and move to several different laptops, you don't want to spend a weekend debugging a 1,000 line notebook just to find something about the environment has changed. That's doubly true if you plan on sharing your notebook. $\endgroup$
    – Quark Soup
    Commented Apr 26, 2020 at 13:43
1
$\begingroup$

The method proposed by Leo Alekseyev and Nasser works, but it is incomplete. There is a serious issue with global declarations in init.m.

As Leo already pointed out, a "privated" notebook will change the content of the context search list contained in $ContextPath. The element "Global`" will be removed, and a private context unique to the notebook will be inserted. But the problem is that a privated notebook also removes all other contexts from $ContextPath except for "System`".

If, for instance, the init.m, loaded and executed only once when a Mathematica process is started, contains DeclarePackage statements, it prepends the contexts of these packages to $ContextPath. This way, the external variables and function names of these packages can be found. But the privated notebook will delete these contexts from the context search list, and the external variables of these packages cannot be found any more, their functions cannot be called, the packages cannot be used.

It is no solution to do the DeclarePackage statements instead in every privated notebook or to repeat them here. This will cause warnings without end, because the system remembers the declarations of these packages already done, and the contexts of the packages will not be prepended to $ContextPath.

But there is an easy solution. I use a template file, let's call it "Notebook_template.nb" (not a Mathematica "Template notebook") from which I create any new privated notebook by renaming and saving it in the destination directory immediately after opening it. In this template the first line is

Get[Notebook_init.m]

and in this batch file I collect all initializiations that have to be done at the time of creation of a new privated notebook. In this file I simply include

$ContextPath=Join[{"Package_1`","Package_2`",...,"Package_n`"},$ContextPath]

in order to repair what was destroyed by the system in the process of creation of the privated notebook. When I have created a new privated notbebook I only need to execute the Get statement, and all external variables and function names of the packages declared in init.m can be found again.

By the way, I even found it usefull to reinclude "Global`" in the context search list, too, and use it as a shared context for all my privated notebooks.

$\endgroup$

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