12
$\begingroup$

Consider our package awesomepackage.m.

If I put this file in FileNameJoin@{$UserBaseDirectory, "Applications"} I can easily import it in any notebook with a simple Needs["awesomepackage`"] (or similar command).

The same still works if I put awesomepackage.m in a subdirectory of Applications, like in FileNameJoin@{$UserBaseDirectory, "Applications","awesomepackage"}.

However, if for any reason I want my awesomepackage to be in some subsubdirectory of Applications, then I will have to use its full path, otherwise Mathematica will not be able to find it based on the context name alone.

Is there some convenient way to have Mathematica look for .m files by default in all (sub..)subdirectories of Applications, maybe up to some nested level? The core idea is that I want to be able to change the exact location of awesomepackage.m without having to change the way it is imported in all the notebooks, and possibly without having to add some code in every notebook in which I want to import this package.

$\endgroup$

1 Answer 1

13
$\begingroup$

The straightforward answer is: Do not try to do this!! If it were possible, it would break things.

There is a specific (and complicated) way Mathematica resolves file names, which allows the standard application structure to work. It is described in the Details section of FindFile. It does not allow for indefinite recursion into subdirectories.

In order for applications to work the way they do, e.g. it is important that foo` resolves to foo/Kernel/init.m and not to foo/foo.m if your directory structure is

Applications
    |
    \- foo
        |
        |- foo.m
        |
        \- Kernel
             |
             \- init.m

The standard application structure is described here.

It is also important that any random .m file that may be part of the implementation of a package and is located within a package's directory shouldn't be loadable by its name — unless it is meant to.

Finally, it is not true that Mathematica searches for .m files in any subdirectory of Applications. foo` can resolve to foo/foo.m but not to bar/foo.m.


If you want to organize your packages and applications into multiple directories, you can do so. But do not put these directories in Applications (or into any other location which is already in $Path), and add each one separately to $Path.

$\endgroup$
7
  • 1
    $\begingroup$ makes sense. But what if I for example have a big and complex package, composed of multiple .m files. I would want the whole thing to be contained in a single directory so to be easily moved and "installed", and at the same time to be able to easily import it in a notebook without having to think of the full paths. What is the recommended method in this case? Should I put a foo.m file where you put it in your example, and in foo.m write some code to tell MMA where to find the various "subpackages" necessary for the main one? $\endgroup$
    – glS
    Aug 23, 2016 at 12:51
  • $\begingroup$ by the way, I didn't find a clear explanation of what init.m does when inside a package directory structure. Can it be used for such purpuses? $\endgroup$
    – glS
    Aug 23, 2016 at 12:52
  • 1
    $\begingroup$ @glS Say the package is called Foo. Then you have a directory with the same name. Within you have multiple .m files, Sub1.m, Sub2.m, etc. The init.m file contains Get["Foo`Sub1`"]; Get["Foo`Sub2`"]; .... You can load the whole package from a notebook using <<Foo` . If the sub-packages are somewhat independent and are meant to be loadable separately too, then that can be accomplished using <<Foo`Sub1` , i.e. the same commands used in init.m. $\endgroup$
    – Szabolcs
    Aug 23, 2016 at 13:22
  • $\begingroup$ @glS Very often, there is a sinlge main package file, Foo/Foo.m and init.m only contains Get["Foo`Foo`"]. Then as your package is growins and you decide to add more sub-packages that Foo.m will depend on, you add them in the same directory as .m files and load them in Foo.m using BeginPackage["Foo`", {"Foo`Sub1`, ...}]. $\endgroup$
    – Szabolcs
    Aug 23, 2016 at 13:24
  • 2
    $\begingroup$ @glS I described how I manage my packages here. You may find it useful. I do not claim that this is the best way, in fact I'm pretty sure it isn't. But it does help me. It's something that grew out organically of my own needs, not something deliberately designed to be generally usable. $\endgroup$
    – Szabolcs
    Aug 23, 2016 at 14:16

Your Answer

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

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