1
$\begingroup$

I have a problem of trying to store some output in an external file.

In one note book I define a function f[x_]:=AdvancedCalculation, where this function generates a relatively large output and is dependent on a significant number of definitions. In another notebook, I would like to have the expression terms=f[x], but I do not want to actually calculate f[x] more than once because it would take too long. Currently I have stored the output of f[x] in a file called Terms.m that has a single line of code.

terms=OutputFromOtherNotebook

I then load this file in my second notebook using the command <<Terms.m.

My current solution is to copy and paste OutputFromOtherNotebook directly from the first notebook into the file Terms.m. I would like to automate this process because larger outputs have become too cumbersome. I am trying to use Put to write the output using the following line of code.

terms=Evaluate[f[x]]>>Terms.m

However, I cannot find the resulting file. Where does the function Put create the file? As a side issue, how can I ensure that f[x] is evaluated before being written to the external file?

$\endgroup$
1
  • 2
    $\begingroup$ Put outputs to whatever directory is returned by Directory[], which is by default your home directory $\endgroup$
    – rm -rf
    Sep 6, 2012 at 1:49

2 Answers 2

4
$\begingroup$

Carl has shown a way to write to the file what you want, but I would suggest to not even put the terms= into the file: you can read the expression and set it to a variable when reading it. It will also get rid of all kinds of complications that occure if you want to write partially evaluated expressions. This approach lets you choose the name of the variable at the time of reading which I think is an advantage as it will make it somewhat simpler to e.g. compare the content of two such files in one session.

As for the directory using SetDirectory is also a perfectly valid solution, but I would suggest to just use full pathes for the files which gives you more control about the location and is much easier to understand and debug, as it is "free" of the current "state" of what the working directory is set to. This is what I'd do:

f[x_] := Expand[(a + b)^100];
fname = FileNameJoin[{NotebookDirectory[], "Terms.m"}];
Put[f[x], fname];

using NotebookDirectory will store "Terms.m" in the same directory as the notebook this is running in, which is very often what you want. You can of course use whatever other directory you want. I'd suggest to look through the predefined directories instead of typing in long machine specific directory names, there are e.g. variables for your home directory, the temporary directory or your documents directory. You can find all predefined directory names by evaluating this:

?$*Directory*

If you already have evaluated f[x] and don't want to rerun it, you might want to use something like:

Put[%,fname]

if the output was the last result calculated. Using something like the following is more robust, as it is independent on how many other things have been evaluated since the call to f[x]:

Put[Out[123],fname]

where the output number (123 in the example) you can read from the output cell tag (these labels can be suppressed in the preferences and it also might not work if you have set $HistoryLength to a low value, it should work with the default settings, though).

To read the expression, just set terms to the return value of Get, as this:

terms = Get[fname];

You might note that << and >> are just shortcuts for Get and Put but will implicitly read the "argument" as a string (<< something is actually equivalent to Get["something"]). So you can't use the shortcuts with a filename stored in a variable as I did, which is a good reason to use the full function names and not the shortcuts...

$\endgroup$
1
  • $\begingroup$ I agree with you that your answer is probably better Mathematica style. It certainly produces a slightly more robust approach for the specific issue I was considering when I wrote the original question. I also think your mention about the built in variables and functions for handling directory names is more robust. $\endgroup$ Sep 6, 2012 at 18:24
3
$\begingroup$

As @R.M. said in the comment, the function Put places the file into the directory returned by Directory[]. This location can be changed by using the function SetDirectory.

I do not know of a way to directly write the expression terms=OutputFromOtherNotebook into Terms.m using Put, but I do have a method using the function Write. The following code writes the desired expression to Terms.m.

WriteString[OpenWrite["Terms.m"], "terms=", InputForm@f[x]]
Close["Terms.m"];

The function OpenWrite["Terms.m"] opens the file Terms.m as an output stream. The function WriteString writes the contents of the string "terms=" literally into Terms.m, and then it writes the value returned by f[x] as input form so that the string can be written directly following the previous string, resulting in the desired expression. The function Close then closes the output stream opened earlier.

This method has the effect of only executing the function f when the file is written, and not when Terms.m is loaded. The use of InputForm is important to ensure that exponents are written in the form x^y by WriteString rather than it's default format, which is as follows.

 y
x

This unusual form would not allow the output to be read correctly using Get.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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