add tag
निरंजन
In LaTeX2e-style, we use `\foo@mycmd` for setting an internal `mycmd` for module `foo`, whereas, in LaTeX3-style (if I understand correctly) we would use `\l__foo_mycmd`. In the discussions related to `@`, the most common reason one may find is: If package `foo` internally uses the command `\foo` and the users of that package define the same command in their documents somewhere, it might break the package internally since the new definition will cause issues in the expected workflow of package `foo`. On the other hand, in the discussions related to the LaTeX3 internal macro, I have mostly heard this: The stability of this macro is not guaranteed. I am quite new to the LaTeX3 paradigm, but one thing I used to really like about the LaTeX2e style was that there used to be _stable_ internal macros. E.g., If I have `\foo@mycmd` in a package written by me, it never used to be like a signal saying "Hey there! `\foo@mycmd` may at any point of time vanish from the code! Don't use it! :knife: :gun:"

In fact, I have freely renewed such internals in my personal code without any fear and haven't had any problem at all. What I want to know is how to write "safe internal macros" in LaTeX3. Internal macros that don't come with the fear of going away. That way I keep one door open to general public to play with the code I write. Otherwise, it seems like a game entirely run and monitored by me. There might be some advantages to the approach using "unsafe internal macros". I am unaware of them, feel free to mention them, but the main question is how to use LaTeX3 internal macros, but NOT mean that they are unstable or risky to be used.
Top Answer
Joseph Wright
In LaTeX2e, the line between macros which are strictly internal, those that are programmatic interfaces and those that are design/document commands is not firmly drawn. This arose in part as the number of control sequences available was very limited when LaTeX2e was developed: as such, something like providing both `\IfPackageAtLeastTF` and `\@ifpackagelater` was simply not feasible: as such, the 'internal' macro `\@ifpackagelater` was _the_ way to make this test for many years.

In the LaTeX3 paradigm, we have four clear layers

- Document commands, for example `\emph`: documented in Lamport's book, `usrguide`,  *etc.*, stable and intended for routine use in an end user source file
- Design commands, for example `\MakeUppercase`: documented in _The LaTeX Companion_, `clsguide`, *etc.*, stable and intended main for setting up classes/appearance. May appear in end user sources (most often in the preamble), but mainly expected to appear in classes/packages/support files.
- Programming functions, for example `\str_if_eq:nnTF`: documented for programmers (API docs), *e.g.* `interface3`, only accessible inside `\ExplSyntaxOn`, should almost always be avoided in a end user source, but will form a large part of packages
- Internal functions, for example `\__str_if_eq:nn`: not documented other than in sources, only intended to be used in implementing programming functions in the same module (so `str` here)

As such, you should decide what programming interfaces you want to provide, and document these. The 'model' package here is [`siunitx`](https://ctan.org/pkg/siunitx), which has both end user docs (`siunitx.pdf`) and for the programmer's API (`siunitx-code.pdf`). If you follow the general `expl3` approach, once you have introduced an API interface, you are (probably) committed to it 'for ever'.

Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.