4

When we look at xparse package documentation there are four related commands

\NewDocumentCommand
\RenewDocumentCommand
\ProvideDocumentCommand
\DeclareDocumentCommand

Similarly there are four commands for environments. When I've learned about \NewCommandCopy I've expected a similar four commands will be available. But looking at LaTeX source I've only found that

\NewCommandCopy
\RenewCommandCopy
\DeclareCommandCopy

are defined.

Is there a technical reason why \ProvideCommandCopy was not defined?

EDIT: Example usecase

In the answer by Phelype Oleinik it is claimed that there is no usecase for such command.

Let's consider that we want to provide a black-and-white switch for the document and we want to use \IfBooleanTF from xparse because we are familiar with it. We know that it exports values \BooleanFalse and \BooleanTrue so we may write for example

\NewCommandCopy\blackandwhite\BooleanFalse

\IfBooleanTF{\blackandwhite}{...}{...}

Let's say we want to pass it when compiling document such as pdflatex '\NewCommandCopy\blackandwhite\BooleanTrue\input{document.tex}'. This will obviously cause errors because \blackandwhite is already defined. If there was \ProvideCommandCopy we could use it to define the default value of \blackandwhite switch in case user does not provide it. Currently we are forced to always define it explicitly.

Obviously there are other ways to make the black-and-white switch work as intended, but I think this is a valid usecase of ProvideCommandCopy.

11
  • In your \blackandwhite use case, \(new|provide)command\blackandwhite{\BooleanTrue} works. I think \NewCommandCopy and friends are mostly for redefining, not aliasing things. May 5, 2022 at 14:29
  • I get ! Use of \??? doesn't match its definition. <argument> \??? ! LaTeX cmd Error: Invalid argument {\blackandwhite } to \IfBooleanTF{\blackandwhite}{a}{b} when trying to use \(new|provide)command
    – nim
    May 5, 2022 at 14:48
  • Sorry, I mean \newcommand and \providecommand. The point is to wrap \BooleanTrue in a macro, not copy it. May 5, 2022 at 14:50
  • @muzimuzhiZ This is what I used: \newcommand{\blackandwhite}{\BooleanTrue}. I got the error mentioned in the previous comment when trying to use \IfBooleanTF{\blackandwhite}{a}{b}.
    – nim
    May 5, 2022 at 14:51
  • Hmm \IfBooleanTF is not as flexible as I think. \expandafter\IfBooleanTF\blackandwhite{a}{b} or use other ways like \csname xxx\endcsname and \ifdefined\xxx <true>\else<false>\fi. May 5, 2022 at 14:59

2 Answers 2

9

There isn't a \ProvideCommandCopy because it isn't useful (and may be harmful even), so the decision was to not implement it. There is a note in the implementation (texdoc source2e, section Copying robust commands in ltdefns.dtx):

A \ProvideCommandCopy isn’t defined because it’s not reasonably useful. \provide... commands mean “define this if there’s no other definition”, but copying a command (usually) implies that the command being copied is defined, so \ProvideCommandCopy doesn’t make a lot of sense. But more importantly, the most common use case of copying a command is to redefine it later, while preserving the old definition, as in: \ProvideComandCopy \A \B  \renewcommand \B { ... \A ... } then, if \A is already defined the first line is skipped, an in this case \B won’t work as expected.

8
  • 1
    I do not understand the provided reasoning. While it is true that the command being copied from usually exists, the command copied to usually doesn't. That's why \RenewCommandCopy exists. It doesn't redefine the original command but the new copy.
    – nim
    May 5, 2022 at 12:20
  • 1
    @nim: the second argument is the more important one: typically you want to use the copy to redefine the original command \B or to keep \B "alive" for other uses, but with \ProvideCommandCopy you have no idea what the content of \A actually is and anyone could destroy your code simply by defining \A. May 5, 2022 at 13:10
  • 1
    Phelype, there is a typo in the text ;-) Comand instead of Command. May 5, 2022 at 13:16
  • @nim "provide" is usually a kind of "backup definition" in case there is no other, but when you are copying a command (#2), it makes no sense to copy if you don't know whether/how it's defined. The definition of the copied-to command would be unpredictable. Should you want to provide a reasonable use-case for \ProvideCommandCopy, we could ponder May 5, 2022 at 13:27
  • 8
    @PhelypeOleinik you should learn from hte older mbers of th latx projct, who nver make typos May 5, 2022 at 13:30
4

I assume most just use the typical commands for writing documents. I think only a small percentage of the user base programs and defines rather sophisticated things at all in TeX/LaTeX.

I think the reasoning for not providing \ProvideCommandCopy in the LaTeX 2ε-kernel is: \ProvideCommandCopy would be a possible pitfall. Besides this \ProvideCommandCopy would be seldom needed. Thus in most scenarios having it in the kernel would imply having something in the kernel that is not used and thus in most scenarios is just ballast. Scenarios where \ProvideCommandCopy might be needed are at an advanced level where the user should be capable of defining it her-/himself. ;-)

I wrote: "I think the reasoning ... is ...". So it is a guess. Neither am I a member of the LaTeX development team, nor do I have much insight, so I can't really speak for that team and justify team decisions.

I'm speculating on this reasoning because I heard it before with similar questions I asked in the past.

But to me it doesn't matter, because for what I need frequently and therefore define frequently, I have my own macro package and extraction routines that—in case of code sharing—extract only those of my own definitions that are really needed. Thus, creating a new template file that contains only those of my own definitions that are needed in the specific scenario is done with one mouse click. ;-)


Instead of arguing with people who for some reason don't want to see that I need what I need, if I felt I needed a \ProvideCommandCopy command, I would simply define it myself.

This is done in the example below.


\DeclareCommandCopy defines the command to be defined in any case, which does not exclude that it is redefined in the process. If redefining takes place, this is done silently, i.e., no error-message or the like is raised.

\RenewCommandCopy defines the command to be defined in any case, which does not exclude that it is redefined in the process. If it is not already defined, an error message is raised beforehand.

\NewCommandCopy defines the command to be defined if it is not defined. If it is already defined, an error message is raised and the command is not redefined.

\ProvideCommandCopy defines the command to be defined if it is not defined. If it is already defined, no error message is raised and the command is not redefined.

The difference between \RenewCommandCopy/\DeclareCommandCopy and \NewCommandCopy/\ProvideCommandCopy is that the further redefine the command to define if it is already defined, while the latter don't redefine it if it is already defined.

The difference between \NewCommandCopy/\RenewCommandCopy and \ProvideCommandCopy/\DeclareCommandCopy is that the further raise an error-message if the command to be defined is (not) already defined, while the latter don't raise an error-message.

All(!!!) these \...CommandCopy-commands do not check whether the command to be copied is defined.

With all these \...CommandCopy-commands the (re)definition is limited to the local scope where the respective \...CommandCopy-command is executed.

With all these \...CommandCopy-commands checking whether the command to be defined is already defined is limited to the local scope where the respective \...CommandCopy-command is executed.

\makeatletter
\providecommand*\ProvideCommandCopy{%
  \declare@commandcopy{\@firstofone}{\@firstoftwo{}}%
}%
\makeatother

\newcommand\CommandToCopy{Copy}
\newcommand\CommandBToCopy{CopyB}
\newcommand\CommandCToCopy{CopyC}
\newcommand\CommandDToCopy{CopyD}

\begingroup

\NewCommandCopy\Copy\CommandToCopy
\message{You should get "\long macro:->Copy" and you get "\meaning\Copy"}

\RenewCommandCopy\Copy\CommandBToCopy
\message{You should get "\long macro:->CopyB" and you get "\meaning\Copy"}

\DeclareCommandCopy\Copy\CommandCToCopy
\message{You should get "\long macro:->CopyC" and you get "\meaning\Copy"}

% \Copy in the current scope is already defined equal to \ComandCToCopy, thus
% \ProvideCommandCopy does not redefine \Copy:

\ProvideCommandCopy\Copy\CommandDToCopy
\message{You should get "\long macro:->CopyC" and you get "\meaning\Copy"}

\endgroup

% Now \Copy is undefined
% \Copy is not defined in the current scope, thus \ProvideCommandCopy within
% the current scope makes \Copy equal to \CommandDToCopy:

\ProvideCommandCopy\Copy\CommandDToCopy
\message{You should get "\long macro:->CopyD" and you get "\meaning\Copy"}

\stop

Console output:

latex-dev test.tex
This is pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020) (preloaded format=latex-dev)
 restricted \write18 enabled.
entering extended mode
(./test.tex
LaTeX2e <2021-05-01> pre-release-1 (develop 2021-2-27 branch)
L3 programming layer <2021-02-18>
You should get "\long macro:->Copy" and you get "\long macro:->Copy"
You should get "\long macro:->CopyB" and you get "\long macro:->CopyB"
You should get "\long macro:->CopyC" and you get "\long macro:->CopyC"
You should get "\long macro:->CopyC" and you get "\long macro:->CopyC"
You should get "\long macro:->CopyD" and you get "\long macro:->CopyD" )
No pages of output.
Transcript written on test.log.

Actually I don't see a proper reasoning for not having \ProvideCommandCopy.
(Note that "having \ProvideCommandCopy" is not the same as "including \ProvideCommandCopy into the kernel". One can, e.g., have a command/macro/function by providing its definition in the preamble or via some home-brewed macro-package.)

Use-cases could include scenarios where \ProvideCommandCopy is used for making another command's definition the default in case the command to be defined is not already defined.

In my humble opinion \ProvideCommandCopy is not more harmful than the other \...CommandCopy commands as long as its usage goes along with sufficient care.

If you want to copy a command for redefining it later, while preserving the old definition, you—be it defined or not—in any case do not use \ProvideCommandCopy for the purpose of storing the old definition:

If \ProvideCommandCopy is not defined you simply can't use it for this purpose.

If \ProvideCommandCopy is defined you don't use it for this purpose because \ProvideCommandCopy is the only one of these commands which allows the scenario of silently not storing the old definition. (With \NewCommandCopy the not-storing is not silent but you get an error-message if storing goes along with overriding something that already exists. Both with \RenewCommandCopy and with \DeclareCommandCopy storing takes place in any case while only the further implies raising an error-message if storing goes along with not overriding but defining anew the macro that is to hold the stored definition.)

I don't think the argument of \ProvideCopyCommand not making much sense due to usually the command to be copied being already defined, is very convincing: The command to be copied is not the command to be defined. The LaTeX-kernel's \providecommand, and thus probably also a (hypothetical) command \ProvideCopyCommand, does not check whether the command to be copied is already defined, but does check whether the command to be defined is already defined.

Loosely based on Forrest Gump: And that's all I have to say about that. ;-)

7
  • Thanks for the detailed answer. Regarding the "defining it myself" comment, I obviously agree, but this question was more about the reasoning for its omission in the kernel.
    – nim
    May 6, 2022 at 10:57
  • While I agree that this command would be rarely used I don't think that it's a good reason for omission. Even advanced users can make mistakes while defining something, and it simply wastes time. Could you elaborate why it's a ballast? The example mentioned in the source2e as a pitfall seems rather unconvincing because this code would behave just as I, and everybody who is familiar with Provide... semantics, expected. Also the document clearly states that the command doesn't make sense, while I think your answer demonstrates that it has perfectly reasonable semantics.
    – nim
    May 6, 2022 at 11:17
  • 1
    @nim If you think \ProvideCommandCopy should be provided (no pun intended), the most likely way to get that would be to open an issue at github.com/latex3/latex2e May 6, 2022 at 13:29
  • @PhelypeOleinik I'm far from pressing inclusion of this into the kernel. For the following reasons: 1) S/he who wants to have \ProvideCommandCopy is free to define it her-/himself. In my answer I showed how to do so. So not having it in the kernel seems not like massive thwarting of features. 2) I am much less able than the LaTeX development team to judge which things it is reasonable to include them into the kernel and thus to push them to the broad user community, and which things it is not reasonable to do because far too few people would use them (correctly). May 6, 2022 at 22:35
  • 1
    @nim I wrote the code for \NewCommandCopy and the documentation, so if you want someone to blame, here I am :) And the reasoning was that it would cause more harm than good, and it would not be terribly useful (as far as I could see). May 7, 2022 at 13:16

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.