21

I have a notebook containing some functions, for example:

f[x_] := 2*x
g[x_] := x^2

Now I would like to convert this notebook to a package, functions.m, which I can call with Get["functions.m"] inside other notebooks, making the functions f[x] and g[x] available.

How can I do this without writing the package from scratch?

In the File menu there is a sub-menu Save As -> Package, but if I save it, and load it withGet["functions.m"], nothing seems to happen in the new notebook; i.e., when I try to use the functions, I get:

f[x]
f[x] 

I guess there is something else that I need to do besides simply saving the notebook containing the function definitions as a package?

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
user9068
  • 297
  • 2
  • 6

3 Answers3

22

If you plan to keep developing the package, you can set up your notebook options so that this is all taken care of automatically.

To have your notebook saved as a package every time you save, open the option inspector and, for your notebook, set Notebook Options->File Options->AutoGeneratedPackage to True. Or, in the front-end, you can type

SetOptions[Notebooks["<notebook name>.nb"][[1]],AutoGeneratedPackage->Automatic]

There is also an option to make new cells initialization cells by default. In the option inspector it is Cell Options->Evaluation Options->InitializationCell (set it to True). The front-end command can be deduced from what is above.

I don't like making my initialization cells code-styled because it seems to disable Mathematica's automatic line-splitting. If you want that, however, change Cell Options->New Cell Defaults->DefaultNewCellStyle to "Code". Why some options have symbol values and some have string values is a mystery to me. You may also want to set DefaultDuplicateCellStyle, the function of which is also a mystery to me.

Tobias Hagge
  • 1,382
  • 9
  • 17
  • 1
    I am very happy with this method but there seems to be one downside. It does not preserve headings (nor text cells). On the other hand Save As Package does preserve these. Is it possible to get the same behavior in an automated method like the above? See also my question https://mathematica.stackexchange.com/q/249494/45020. – Kvothe Jun 11 '21 at 15:01
18

When you save a notebook as a package, the only cells that are setup to be evaluated when the package is loaded are Initialization cells. If you change the cell style to the code style, the initialization property is set automatically (this style has the shortcut alt+8) and the cells are distinguished by a darker background. You can also do this by marking the cell, right clicking and selecting "Initialization Cell".

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
jVincent
  • 14,766
  • 1
  • 42
  • 74
13

You can do this with the Save function.

First define some symbols in a notebook:

f[x_] := 2^x-1
g[x_] := 1/f[x]

Evaluate the definitions.

Now use Save to write them to a file:

Save["functions.m", {f, g}]

Now f, g, and all their dependencies have been written to the file.

Loading the file with Get["functions.m"] will load the definitions into the kernel.

Joel Klein
  • 5,225
  • 1
  • 31
  • 44
  • What directory does this go into? It seems to go into a random one of the directories in $Path. Is there some way to change which directory this saves to by default? – Mike Battaglia Oct 11 '22 at 19:50
  • Directory[] returns the current working directory, change it with SetDirectory[]. Be aware this pushes onto a directory stack, go back to previous with ResetDirectory[]. You can change the default by putting a SetDirectory call in $UserBaseDirectory/Kernel/init.m – Joel Klein Nov 01 '22 at 18:52
  • You can also provide an absolute path to Save. But just like anywhere else, relative paths are relative to the current working directory, which is what Directory[] tells you and SetDirectory can change. – Joel Klein May 25 '23 at 18:19
  • 1
    NotebookDirectory[] returns the path the actual notebook is in. You can save the .m file in the same directory where its "mother notebook" resides by invoking Save[FileNameJoin[{NotebookDirectory[], "functions.m"}], {f,g}]. – András Aszódi Feb 16 '24 at 14:40