Group Abstract Group Abstract

Message Boards Message Boards

2
|
21K Views
|
13 Replies
|
2 Total Likes
View groups...
Share
Share this post:

How do I set up multiple .m files in a package?

I have read through the documentation and watched the videos. I even poked around to find older material.

I think I understand how to set up a package in Workbench.

However, all the examples I have seen have a single .m file for the code.

I want to make a package/application that has multiple source files.

How do I do this?

Does each .m file have to have its own BeginPackage[]/EndPackage[] context, or can there be just one .m file that sets the context and the other source files are included as optional arguments to the only BeginPackage[] function call?

In the past, packages have been set up with a 'master' package that was called (Get[] or Needs[]) that would load all the sub-packages -- each of those could the loaded individually. How would I go about setting this up?

Thanks.

13 Replies

As the original poster, I would like to thank everyone for this excellent discussion. I have a lot of ideas to test out.

Clearly, this topic is complicated enough to have some 'official' tutorial from Wolfram Research. I am hopeful that with the release of Workbench 3, there will be a revision in the classes to go along with it. At one time, I was promised a second level course on Workbench and advanced programming topics, but this topic seems to have been lost in the ever lengthening list of things to do.

I can understand this, because this topic is of little interest or use to the vast majority of Wolfram language users -- those who use the tool as a big graphical calculator or rapid prototyping tool. However, the strength of any language's culture is the degree of support it provides to those people who want to push the envelope.

I find this rather difficult to understand Pieter. Can any package refer to an exported symbol from any other package, regardless of their relative positions in the tree structure? Can P1 make a hidden import of P2 and P2 make a hidden import of P1? Are the multiple packages no longer loaded by the init.m file?

If exported names are only known at the next higher level in a tree does that mean that the ultimate user can't use those lower level routines?

What does "He/She then subdivides his module in files using Get as a stub to a placeholder section." mean? Is a "module" a set of package files, each of which may have hidden imports? And what is GIT and GIThub?

This sounds like a method that is heavily dependent on the tree structure and not at all flexible.

A system that established the contexts of all exported symbols (to the ultimate user) first and only then established the definitions in the Private sections would be much more robust - and simpler.

Posted 12 years ago

This is an excellent question. First my own remarks on programming in the wolfram language. First I have a general idea on what to create. (the algorithm is my invention and the computer only executes it)

I create a few snippets of code for the crucial areas to check how complicated or easy the problem is (storyboard coding). Then I create a flowchart of input and output-data-formats and function names. This exercise creates more insight in the problem and in most of the times it simplifies the solution approach. (do I need global data objects or will I go for the non global symbols approach)

Then I create two notebooks. One to program the functions and one to test the functions. After programming the next function in the flowchart I test the function in the testnotebook (the programming notebook can be kept clean by doing all experiments in the testnotebook). When a few new functions have been added and tested it is time for an integration test by running the full testnotebook. So before I look at the Workbench all programming is done in 2 notebooks.

Every set of functions in my flowcharts are subdivided into more aggregated blocks of code. The idea is to put every aggregated block of code into a subpackage and then merge it all together into 1 Main[] function. So subpackages need to roll-up into 1 main package and my global variables need to be global to only the mainpackage context. Let's load subpackage P1 and P2 and the globalvars package.

BeginPackage["Main"] main::usage = "main[]..." Needs["Globalvars"] Needs["P1"] Needs["P2"] Begin["Private"] main := .... End[] EndPackage

The most important thing is not to include P1 and P2 in the second argument of BeginPackage. The reason is that they are Needs that are executed before the BeginPackage command itself. This puts P1 and P2 on the contextpath before Main is added. The problem arises when EndPackage is executed. This switches back to the contextpath status before Beginpackage. So P1 and P2 stay on the contextpath when leaving the package. The way Needs is used here is called Hidden import.

Now there is a new trick in M10. Usage exports a function from the private to the package context. But this now also works of a package in a package in a package. Every usage function is now visible to only the 1 level higher package. With this approach all your symbols are recognized in all your packages and you never have to use full context to refer to something. So you end up with only 1 context added to the ContextPath when you arrive back in the global context. You global symbols are now global to the context Main and lower so there is not issue if the use accidentally creates the same names in Global` context.

This is the moment when I start to use the workbench. I import my programming and testing notebooks and create .wl files for the package structure I need. This structure by the way depends very much on the number of programmers involved. Every programmer gets a part of the overall function flowchart. He/She then subdivides his module in files using Get as a stub to a placeholder section. The workbench has support for GIT and via GIThub you get version management control on the whole team. When you start to do some builds it is good to now you have all documents, notebooks, packages etc. in one place. In some occasions programmers de-rail into developing a solution and feel the needs to switch a few versions of their files back. This is easy when the package files are organized by programmer.

The new nested packages approach is a great addition to developing large programs in the Wolfram language since you organize by programmer and by aggregated package and execute version management on each of these files.

POSTED BY: Updating Name

George, I have one reply and one posting on Wolfram Community that may be useful to you.

The first basically shows how to lay out an application with multiple packages. You essentially load all the packages through the init.m file. This reply is in:

http://community.wolfram.com/groups/-/m/t/393033?ppauth=L19VHYIc

The second is my posting on:

Large Multipackage Applications

This deals with the problem of not maintaining a strict tree order - which may be difficult or inconvenient to do. I have two small zip files, ContextProblem.zip and ContextFix.zip that illustrate the problem and a fix for it. The problem is that the BeginPackage statements read all the packages listed in the second argument and establishes definitions. If the context of some symbols is not known they get pushed into the Private context. A correct definition may later be established when the package itself is read in. But it's hit or miss which one will be used. The solution is to use the init.m file to first read in all the packages to establish contexts but Clear all the symbol and Private definitions when reading each package. Then, with all the contexts established, read them again. That appears to work but I haven't done large scale testing on it.

It really would be nice if a Workbench for documenting that was simple to use and clearly documented itself was provided. I view it as essential for serious Mathematica usage in science and mathematical applications.

David, I have investigated your "Context Problem example". One of the issues (I think) is the use of Needs in the BeginPackage statement. Let me know what you think about my reply to George?

Pieter, yes, let me read your comments more carefully later on and experiment a bit. I didn't know about the version 10 behavior of usage messages that you describe (is it documented somewhere that you can point me to?). The only immediate issue with that of course is if the package is to be used for an earlier version of Mathematica. But let me look over your comments later on when I have some time and I will respond.

POSTED BY: David Reiss

Yes, do some simple experiments to see if you have the general idea scoped out and let me know if you get to a point of confusion or contradiction...

POSTED BY: David Reiss
POSTED BY: David Reiss
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard