2
$\begingroup$

In order to keep my code modular, I have defined some functions in "Foo.wl" file, which I source with Needs["Foo`"].

When I modify a single function in Foo, I quit the kernel and reload Foo in order to ensure that the modified functions are reloaded. Is there a way to ensure that Mathematica automatically reloads only the changes? I don't want to have to request Mathematica to specifically clear some function.

EDIT: To clarify, my package has multiple functions (to be numerically evaluated). I think Mathematica does a good job of optimizing repeated calculations by caching the values of function calls.

So I do not want to reload the whole package. I want Mathematica to reload only those functions which have changed.

EDIT2: An explicit example. I have some functions defined in an external ".wl" file, Eg: f[x_]:=f[x]=x^2; g1[x_]:=g1[x]=x^3; g2[x_]:=g2[x]=x^4; Suppose I source this using Needs or Get and do Plot[{f[x],g[x]},{x,0,100}]. Plotting the same thing again will give near instantaneous results (even when $f,g_1,g_2$ are complicated functions) since the values are "memoized". If/when I change the definition of $g1,g_2,\ldots$ in the ".wl" file, I would like to be able to reload their definitions,without losing the memoized values of $f(x)$.

$\endgroup$
  • $\begingroup$ I think you're asking how to reload the package without quitting the kernel like you currently do, right? $\endgroup$ – sblom Apr 22 '15 at 21:37
  • $\begingroup$ I've clarified my question. $\endgroup$ – Siva Apr 22 '15 at 21:44
  • $\begingroup$ Okay. I'm less sure of my previous answer now, but this is the sort of thing it seems like @LeonidShifrin would totally be able to answer. $\endgroup$ – sblom Apr 22 '15 at 21:47
  • $\begingroup$ This is probably possible, and an interesting (and important) problem, but this isn't very easy to make robust. Basically, one needs both static analysis on the code, and dynamic analysis on the loaded version, and then a kind of a diff that would tell what the changes are, and then functionality to properly load those changes. We have bits and pieces needed for this scattered in the answers on this site, but this doesn't strike me as a simple project. I will keep it in mind but can't give a good answer right away. You may have luck with some partial solutions. $\endgroup$ – Leonid Shifrin Apr 22 '15 at 22:33
  • 1
    $\begingroup$ One thing you can do is to develop in the FrontEnd, and have your cell context set to whatever your package's private context is (Foo`Private` ). You can then execute it inside BeginPackage["Foo`"] - EndPackage[]. In such a case, you will automatically patch your loaded code, and only with the changes you actually make. When the code is complete, you can move it from FrontEnd to the file. $\endgroup$ – Leonid Shifrin Apr 22 '15 at 22:36
2
$\begingroup$

Your memoized values are not lost when the package is reloaded, so long as you do not quit the kernel.

I did a couple of tests as follows. First without packages, just in the notebook:

In[125]:= f[x_] := f[x] = x^2

In[126]:= Table[f[i], {i, 10}]

Out[126]= {1, 4, 9, 16, 25, 36, 49, 64, 81, 100}

In[127]:= f[x_] := f[x] = x^3

In[128]:= Table[f[i], {i, 15}]

Out[128]= {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 1331, 1728, 2197, 2744, 3375}

As you can see, the first 10 values remain squares, not cubes. Then I made a test package in which I defined f[x_] := f[x] = x^2 and saved the file.

Get["TestPackage`"]
Table[f[i], {i, 10}]
(* {1, 4, 9, 16, 25, 36, 49, 64, 81, 100} *)

Then I went to the package and changed the definition to f[x_] := f[x] = x^3 and saved again.

Get["TestPackage`"]
Table[f[i], {i, 10}]
(* {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 1331, 1728, 2197, 2744, 3375} *)

So no loss of memoized values.

If, however, your question is on how to only run those cells of a package, which have been modified, when reloading, I'm afraid I don't have an answer for that.

$\endgroup$
1
$\begingroup$

If you merely wanted to reload the package without restarting the Kernel you could use Get; see: When to use Get vs Needs.

Since you want a partial reload I suggest writing the Package in parts; you could use e.g. Foo1.m, Foo2.m, Foo3.m etc. (or more descriptive names realistically). Then use Foo.m simply to load these other Package files. This way you can do a Get["Foo2.m"] to reload only that functionality.

Of course if you can simply edit the definitions in memory as Leonid suggested do that instead, but I assume that for whatever reason you cannot or do not want to do that.

$\endgroup$
  • $\begingroup$ Thanks for pointing out that I can use Get instead of Quit and then Needs. However, my main interest is in the question of a partial reload, so that I don't lose cached function values. Does Get differ from Needs in that respect? $\endgroup$ – Siva Apr 23 '15 at 5:35
  • $\begingroup$ @Siva It is simply not clear enough to me what you want kept and what you want reloaded. Are these "cached function values" part of the function that you are modifying? How is that supposed to work? We need more details and preferably concrete examples to make a solid recommendation. $\endgroup$ – Mr.Wizard Apr 23 '15 at 5:39
  • $\begingroup$ I have given an explicit example now. Let me know if it is still not clear. Thanks. $\endgroup$ – Siva Apr 23 '15 at 7:07
  • $\begingroup$ Not entirely clear, I'm afraid. If you change the definitions of the functions, don't the memoized values become invalid? $\endgroup$ – LLlAMnYP Apr 23 '15 at 16:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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