# What is the difference between \cs_if_exist:NTF and \cs_if_free:NTF?

I don't understand what difference of existance and being free means. Consider this example:

\documentclass{article}
\usepackage{expl3}

\begin{document}

\ExplSyntaxOn

\cs_new:Npn \my_cs: {}

\verb=\my_cs:= ~ does ~ \cs_if_exist:NF \my_cs: { not ~ } exist \\ % exists
\verb=\my_cs:= ~ is ~ \cs_if_free:NF \my_cs: { not } ~ free \\ % not free

\tl_new:N \l_my_tl

\verb=\l_my_tl= ~ does ~ \cs_if_exist:NF \l_my_tl { not ~ } exist \\ % exists
\verb=\l_my_tl= ~ is ~ \cs_if_free:NF \l_my_tl { not } ~ free % not free

\verb=\l_tmpa_tl=~does~\cs_if_exist:NF \l_tmpa_tl { not ~ } exist \\ % exists
\verb=\l_tmpa_tl=~is~\cs_if_free:NF \l_tmpa_tl { not } ~ free % not free

\ExplSyntaxOff

\end{document}


Can a cs exist and be free? Or is the difference more a semantic one?

-

I show the output of \cs_show:N \cs_if_free:NTF and of \cs_show:N \cs_if_exist:NTF (formatted for better readability)

\cs_show:N \cs_if_free:NTF

> \cs_if_free:NTF=\long macro:
#1->\if_meaning:w #1\scan_stop:
\prg_return_true:
\else:
\if_cs_exist:N #1
\prg_return_false:
\else:
\prg_return_true:
\fi:
\fi:
\c_zero .

\cs_show:N \cs_if_exist:NTF

> \cs_if_exist:NTF=\long macro:
#1->\if_meaning:w #1\scan_stop:
\prg_return_false:
\else:
\if_cs_exist:N #1
\prg_return_true:
\else:
\prg_return_false:
\fi:
\fi:
\c_zero .


If the meaning of #1 is \relax (aka \scan_stop:), the former returns true and the latter returns false, so \relax is free and does not exist. Otherwise the tests use \if_cs_exist:N, that is, \ifdefined, and the results are likewise opposite.

I think it's only a matter of convenience to have two tests that are, in fact, equivalent up to switching the arguments.

According to Joseph Wright, the two tests might have not been reverse of each other at some point in time, but they are nowadays.

-
Hmm... this means every existing command is not free and every free command does not exist. For me this sounds like the same thing with a different name. \cs_if_exist:NT is the same as \cs_if_free:NF and vice versa. –  clemens Feb 9 '12 at 22:02
Oh. I overread that you stated that in your answer as well :) –  clemens Feb 9 '12 at 22:04
Yes and no. :) Try and see their meaning: \cs_if_free:NF seems to be slightly more efficient than \cs_if_exist:NT (and conversely, switching F and T). –  egreg Feb 9 '12 at 22:07
I'm afraid I am not really able to tell what efficiency means in this context. Will the one be faster than the other? (Can't be much on a scale observable by human beings, anyway ;) ) –  clemens Feb 9 '12 at 22:20
As coded now in expl3, the F conditionals are slightly faster than the T conditionals. Really, I optimized the TF conditionals, and then the F conditionals come by just adding {}, while the T conditionals need \use:n \use_none:n to go from the TF logic to the T logic. This is true of all conditionals in expl3. I try very hard not to take that into account when writing code because it may change (but as I'm perpetually striving for speed, that's difficult to forget). –  Bruno Le Floch Feb 9 '12 at 22:37

As egreg describes, the two conditionals can be used interchangeably in all cases (up to exchanging the <true> and <false> branches, of course).

The only difference is semantic. For instance,

\tl_new:N \l_foo_tl


starts with

\cs_if_free:NF \l_foo_tl { <error> }


but

\tl_use:N \l_foo_tl


contains roughly

\cs_if_exist:NF \l_foo_tl { <error> }


In both cases, we are trying to assert that a given condition holds: either check that the token list variable is free to define, or check that the token list is defined and won't trigger an error when used.

-

These commands were purposefully defined as a pair but their behaviour was not always symmetric. The original intention was to have a loose definition along the lines of:

\cs_if_free:NTF — is it allowable to create a new cs with this name?
\cs_if_exist:NTF — has the cs been created?

For quite a while, \cs_if_free had some extra branches to sanity check its input. E.g., only the kernel should define commands with :D suffixes, so return false. Actually that might have been the only difference :). You could imagine a few other such checks according to the conventions of the expl3 naming scheme.

As some point we decided that all this was overkill and simplified the behaviour, and at that point the two commands became logically symmetric. But I'd still recommend as a point of style to use them in your code according to the definitions above.

If we were to start again, I think it would be better to only have a single command name.

-
Thanks! This finally clears the reasoning behind those two. –  clemens May 22 '12 at 9:09