"Making a symbol public" in practice means creating the symbol as
MyPackage`MySymbol
and not as
MyPackage`Private`MySymbol
The typical way to do this is to "mention" the symbol before Begin["`Private`"]
. This mention does not have to be in a usage message. You can just write the symbol name in that section, like this:
BeginPackage["MyPackage`"]
MySymbol
Begin["`Private`"]
MySymbol::usage = "MySymbol does this and that.";
MySymbol[x_] := x^2
End[]
EndPackage[]
This is the solution I recommend for you.
But as I understand your question, you are asking to avoid even doing this, and have everything about MySymbol
together on adjacent lines of the source file.
For a trivial package like the above this is achievable like this:
BeginPackage["MyPackage`"]
Begin["`Private`"]
(* first mention of MySymbol is here: *)
MyPackage`MySymbol::usage = "MySymbol does this and that.";
MySymbol[x_] := x^2
End[]
EndPackage[]
The symbol is created at its very first mention. Make sure that you explicitly create it in the correct context (MyPackage`
). Subsequent occurrences of MySymbol
will be found by the system in the in the MyPackage`
context.
I do not suggest you do this though. Imagine that at some point you add a second symbol that depends on the first one:
BeginPackage["MyPackage`"]
Begin["`Private`"]
MyPackage`SecondSymbol::usage = "SecondSymbol[]";
SecondSymbol[] := MySymbol[123] (* now first mention is here!!! *)
MyPackage`MySymbol::usage = "MySymbol does[x] this and that.";
MySymbol[x_] := x^2
End[]
EndPackage[]
Now the first mention of MySymbol
may occur earlier, and it is very easy to forget to add the full context to it. The risk of introducing bugs is too high, so I do not think it's a good idea to try to keep all lines together.
It's better to "declare" all public symbol at the beginning (without a usage if you prefer), similarly to how one must do the same in C or C++. In C, a function must be at least declared (if not defined) before its first use. If you don't, the compiler will give you an error. Mathematica is more dangerous because it won't give you an error, things will just not work as you expect.
It's easy to see that within the documented functionality of Mathematica there is no safe way around mentioning the public symbols at the beginning. This is because Mathematica does not read the package source at once. It reads and evaluates it line by line. You are asking to make all symbols with a usage automatically public. But when Mathematica first encounters such a symbol, it does not yet know if it will get a usage later in the file. Thus what you ask is not possible within documented means.
But there is an undocumented package format which allows it. It is described here:
With this package format, Mathematica first parses the entire source file and decides on the context of each symbol in advance, based on the PackageExport
declarations. It will evaluate the lines only afterwards.
The package would look like this:
Package["MyPackage"]
PackageExport["MySymbol"]
MySymbol::usage = "MySymbol[x] does this and that";
MySymbol[x_] := x^2
What's public is decided not based on the usage but based on PackageExport
. The PackageExport
line may be located anywhere within the file.
Thus this method allows doing almost exactly what you were asking for. I am hesitant to recommend it though because it is not documented, and it has undergone some changes since version 10.0. Specifically, how $Context
and $ContextPath
are set while reading the package has changed in v11.0. I use this package format myself (for reasons different from yours), and originally this caused some problems which were not easy to work around. If you run into trouble like this, you will be on your own solving it. You won't find any documentation and Wolfram Support will likely refuse to assist.
I suggest to stick to the classic package format, mention the public symbols at the beginning, and only move the usage message to be together with the rest of the definition.
Begin["`Private`"]
is enough. $\endgroup$