Suppose that an application needs to be configured specifically for a user's system. e.g. the application needs to be told the location of certain data directories. What is the best way to provide this possibility to the user, so that the user doesn't have to enter this information every time they load the package?

  • $\begingroup$ Ideally, I think I would like for the user to provide a variable setting which was only activated once the package was loaded, and which then lived in the package context. This might be achieved by the package loading a specific file on startup. Something like $UserBaseDirectory/ApplicationConfig/MyApp/config.m. Is there a convention for this? $\endgroup$ – Ian Hinder Aug 24 '12 at 13:56

I can name two ways off the top of my head:

  • Provide global variables which the user can reset in their init.m - this is what you described. If you define these variables in your package (namespace), then the user will always be able to refer to those variables by their long name in cases of collisions: MyAppContext`$MyAppDataDirectory.
  • Provide a separate initialization file (e.g. Settings.m), which is loaded by your application (and located e.g. in the Kernel folder), where you can specify a number of properties e.g. as a list of rules, such as

       "ApplicationDataDirectory" :> Automatic,

    so that the user can modify some of these rules.

The second approach seems cleaner to me (since it does not involve user's interaction with the internal state of your application), particularly when there are many properties which you'd like to make user - configurable.

  • $\begingroup$ How would one access the Settings.m file? Would it be simply: MyAppKernelSettings (assuming a directory structure of MyApp/Kernel)? $\endgroup$ – rcollyer Aug 24 '12 at 18:59
  • $\begingroup$ @rcollyer The Settings.m file is not supposed to be accessed programmatically by the user, who is supposed to simply change some settings in the file. The application would normally have some internal variable storing its own location which is determined by InputFileName during the loading. Then, the application would know the relative path of the Settings.m, w.r.t. the main application folder - and access it in this way,through its full file name that it will dynamically construct. There is no reason to give Settings.m a separate context, it can simply be imported using Import. $\endgroup$ – Leonid Shifrin Aug 24 '12 at 19:08
  • $\begingroup$ Where should Settings.m live? In the application's own directory, or in the user's configuration directory (i.e. ~/.Mathematica or ~/Library/Mathematica etc)? I think the latter, as the application directory might be shared between users or not be writable, and might also be overwritten when the application is upgraded. If it should be in the configuration directory, is there a standard convention for where exactly to put it? $\endgroup$ – Ian Hinder Sep 7 '12 at 7:28
  • $\begingroup$ @IanHinder For some reason didn't see your comment before now, discovered it by accident ... One of the standard places for applications is $UserBaseDirectory/Applications. If this is the application where your app will be installed, then it should both be writable and should not be overwritten during upgrades, AFAIK. I may be wrong, but if memory serves, my apps residing there were never removed during the upgrades. $\endgroup$ – Leonid Shifrin Sep 10 '12 at 18:07
  • $\begingroup$ @Leonid We recommend that our application is installed there, but it could also be installed somewhere else that Mathematica looks for application (e.g. globally). I just think it's bad programming practice to store user-specific data inside an application code directory. $\endgroup$ – Ian Hinder Oct 2 '12 at 23:18

At the moment, we ask users to set a certain variable in their init.m file, and the application then uses this variable. i.e.

$MyAppDataDirectory = "/home/me/mydata";

Since this symbol is set first in the user's init.m file, before the application is loaded, it is created in the Global context. The application then refers to this variable as GlobalMyAppDataDirectory. This could theoretically cause silent problems if another package happened to also use $MyAppDataDirectory.

  • 1
    $\begingroup$ I think this should really be an addendum to your question... it would provide some good background and context to what you're doing. As an answer, this feels empty because you're not justifying or arguing for a design choice (which is what the question is about), but merely stating what's being done now $\endgroup$ – rm -rf Aug 24 '12 at 15:44

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.