Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"\@namedef" in xparse #179

Closed
wspr opened this issue Jul 8, 2014 · 67 comments
Closed

"\@namedef" in xparse #179

wspr opened this issue Jul 8, 2014 · 67 comments
Assignees
Labels
enhancement New feature or request xparse Historical: see latex3/latex2e

Comments

@wspr
Copy link
Contributor

wspr commented Jul 8, 2014

I'm seeing a few cases on tex.sx of things like

\expandafter\NewDocumentCommand\csname #1\endcsname

I wonder if this indicates that we should possibly provide supported variants of \NewDocumentCommand and friends that take csname-type input. I don't have any good suggestions on what we could call these.

Alternatively, we could instead provide a prefix command such as

\WithCSname \NewDocumentCommand {#1}

that's internally just \exp_args:Nc. (I don't like \WithCSname though.)

@wspr wspr added the xpackages label Jul 8, 2014
@FrankMittelbach
Copy link
Member

Am 08.07.2014 08:48, schrieb Will Robertson:

I'm seeing a few cases on tex.sx of things like

|\expandafter\NewDocumentCommand\csname #1\endcsname
|

I wonder if this indicates that we should possibly provide supported
variants of |\NewDocumentCommand| and friends that take csname-type
input. I don't have any good suggestions on what we could call these.

do you have a few pointers on the use cases?

In my opinion this looks simply like a misuse of interface layer to me
and while I know it will still take ages to educate .. I don't think
that we should necessarily encourage that.

However, I might be mistaken and this is why I would like to see examples

Alternatively, we could instead provide a prefix command such as

|\WithCSname \NewDocumentCommand {#1}
|

that's internally just |\exp_args:Nc|. (I don't like |\WithCSname| though.)

even more 'orrible :-)

frank

@wspr
Copy link
Contributor Author

wspr commented Jul 9, 2014

A Google search yielded fewer results than I expected.

I agree that generally people are just using it wrong. I guess I just wanted to flag that it was happening; let's leave it along for now.

@josephwright
Copy link
Member

Find use cases.

@josephwright
Copy link
Member

I'm pretty sure we are taking the position 'do not do this' ...

@eg9
Copy link
Contributor

eg9 commented Sep 23, 2018

A “use case”, admittedly not really so explicitly useful

https://tex.stackexchange.com/questions/378342/

@wspr
Copy link
Contributor Author

wspr commented Sep 24, 2018

If we don't provide variants of the standard commands, I think we still need to address how to create document-level macros with "constructed" names.

For example, in a "newfloat" style package, maybe I have a command \newfloat{listing} which creates the document-level command \listoflisting.

Packages like refstyle which create commands like \tabref / \tablabel and so on but are extensible to allow referencing to other document elements.

Any package which defines its own \NewFoo / \RenewFoo / \DeclareFoo / \ProvideFoo probably wants to construct those names rather than hard-code.

I can't see a way around doing this kind of thing without having the equivalent of \@namedef. Here's a (probably crazy) thought: allow syntax like \NewDocumentCommand{listof#1} — which checks whether the first argument is a csname or braced balanced text and uses N or c accordingly...

@blefloch
Copy link
Member

blefloch commented Sep 24, 2018 via email

@josephwright
Copy link
Member

One can just do

\use:x
  {
    \NewDocumentCommand \exp_not:c { name }
  } ...

thought I do see that this is sub-optimal. I guess @FrankMittelbach may have thoughts on this: xparse is meant to make the document API self-declaring, but I doubt people want to have to do

\listof{things}

and so forth for every case which is not hard-coded.

@FrankMittelbach
Copy link
Member

FrankMittelbach commented Sep 24, 2018 via email

@wspr
Copy link
Contributor Author

wspr commented Sep 24, 2018

On naming, what do you think of my tongue-in-cheek suggestion to have

\NewDocumentCommand\foo ...
\NewDocumentCommand{foo}...

be equivalent? :) We don't need these to be fast, after all.

@stone-zeng
Copy link
Contributor

But how about \NewDocumentCommand{\foo} then?

@eg9
Copy link
Contributor

eg9 commented Sep 24, 2018 via email

@FrankMittelbach
Copy link
Member

precisely. Which is why I think it needs a different name for declaration. You can of course invent another type of syntax, e.g. \DeclarDocumentCommand!{foo} but that is out of the normal way too and I wouldn't think it helps or reads well. If at all then, we should use *. It may seens initially confusing because of \newcommand*but then we do provide with xparse a different meth for "long" arguments and so that may be an option that people soon grasp.

@FrankMittelbach
Copy link
Member

Returning to this topic ... what about:

\NewConstructedDocumentCommand
\RenewConstructedDocumentCommand
\ProvideConstructedDocumentCommand
\DeclareConstructedDocumentCommand

Rationale: this is lengthy but understandable.

  • length is not a problem because it is not needed often
  • understandable name is useful
  • if it is needed then there is currently no decent way to do it except with \expandafter and the like
  • it also works nicely enough with the "Expandable" declarations, e.g., \NewConstructedExpandableDocumentCommand

@josephwright
Copy link
Member

@FrankMittelbach Names are good, the question was always whether this belongs at all at the document-command level. The alternative I think was always that such constructs should arise from an expl3 function in which the c-type expansion will take place internally, of the form

\cs_new_protected:Npn \module_funct:n #1
  {
    % Stuff
    \@@_internal:c {#1}
  }
\cs_new_protected:Npn \@@_internal:N #1 
    {
       % Stuff
       \NewDocumentCommand #1 ...
    }
\cs_generate_variant:Nn \@@_internal:N { c }

@FrankMittelbach
Copy link
Member

FrankMittelbach commented Dec 14, 2021 via email

@josephwright
Copy link
Member

@FrankMittelbach I was mainly worried we want to be as clear as we can about the fact that creating document commands should be explicit. There are use cases as you say for creating them on-the-fly: I'm entirely happy with the suggested names.

@eg9
Copy link
Contributor

eg9 commented Dec 14, 2021

@FrankMittelbach

The names might be

\{New|Renew|Provide|Declare}NamedDocumentCommand

but Constructed is good as well.

They should come with a big warning; at least some people will read them.

@dbitouze
Copy link
Contributor

\{New|Renew|Provide|Declare}NamedCommand

Sounds better IMHO.

They should come with a big warning

I am looking forward to it, since I'm not sure to see what's wrong...

@FrankMittelbach
Copy link
Member

The names might be

\{New|Renew|Provide|Declare}NamedCommand

but Constructed is good as well.

that would match the old internal \@namedef but but I'm not sure that should be a guiding principle as there is no "command" in the old 2e name: in my opinion the opposite of a "named" command would be unnamed command and that is not what it different between the two, I still vote for Constructed (or even ConstrcutedCommandName if you want to be technically correct :-)

@josephwright
Copy link
Member

I think we want DocumentCommand in there somewhere

@FrankMittelbach
Copy link
Member

I think we want DocumentCommand in there somewhere

oh sure, I meant to write \NewConstructedDocumentCommandName(but I wasn't that serious). I think my original proposal is just fine, i.e., \NewConstructedDocumentCommand. And yes, even in Enrico's proposal there should be "Document" so it would be \NewNamedDocumentCommand which is even less appealing to me.

@blefloch
Copy link
Member

Joseph suggested to just use \exp_args:Nc on the programming side, namely

\cs_new_protected:Npn \module_funct:n #1
  { ... \@@_internal:c {#1} ... }
\cs_new_protected:Npn \@@_internal:N #1 
  { ... \NewDocumentCommand #1 ... }

This mixes expl3 and document level, as Frank objected. But I don't understand how \NewConstructedDocumentCommand would help: you still have to call it from somewhere inside expl3 code, no? E.g. in the nfloat example

\NewConstructedDocumentCommand{listof #1}{}{ \nfloat_list:n {#1} }

still needs to get #1 from somewhere. I don't see how to avoid this mixing.

On a separate note, a variant of Will's idea is to allow \NewDocumentCommand{/foo}, namely recognize when the argument starts with a slash and treat this as a csname. This takes care of stone-zeng's objection: if the csname is itself stored in some macro \name, then just do \NewDocumentCommand{/\name} to get the result of \csname\name\endcsname.

@car222222
Copy link
Contributor

But Is “Constructed” understandable or at all meaningful here? Noting that these commands are no more or less “constructed” than any other command, not even the name is is “constructed”

The only distinction is how the name is specified (no ), and of course what characters it can contain. Neither of these are implied by the word “Constructed”, especially since this qualifies the command and is apparently unrelated to the name specification.

“ByName” or “Named” may work (a little) better?

Possibly @blefloch 's idea of a specialised indicator that the name argument has to be preprocessed (and has a larger alphabet). Then there is no need for a new name, however long!

@davidcarlisle
Copy link
Member

But Is “Constructed” understandable or at all meaningful here? Noting that these commands are no more or less “constructed” than any other command, not even the name is is “constructed”The only distinction is how the name is specified (no ), and of course what characters it can contain. Neither of these are implied by the word “Constructed”, especially since this qualifies the command and is apparently unrelated to the name specification.

Must admit ...ByName had occurred to me as well as perhaps more informative than ...Constructed..., but a perhaps more useful form would be not to add variants of \NewDocumentCommand and \RenewDocumentCommand but instead expose \exp_args:Nc  as say \UseByName   then

\UseByName\NewDocumentCommand{foo**bar}{...}

but also

\UseByName\newcommand{zzz}{...}

or anything else where you are tempted to use \expandafter\something\csname

@FrankMittelbach
Copy link
Member

\NewDocumentCommandByName might be even better. Bruno's specialized convention would work too but {/foo} looks odd (to me at least).

However, David's idea of \UseByName seems to me superior, as indeed it comes up in other cases for 2e style coding like \UseByName\setlengthand it would mean a single command for all such cases.

@u-fischer
Copy link
Member

I also like David's idea. How should peoble than use such a command? So what would be the counterpart of @nameuse?

@blefloch
Copy link
Member

Again, I don't see in what situation anyone would use \ExpandNc\NewDocumentCommand (or any other name like \NewDocumentCommandByName). The argument must be something constructed, so it must come as the argument of some other macro, in which case this looks an awful lot like programming. Do you have a concrete case in mind?

Basically I'd advocate having \csuse = \use:c (and even this, I'm not sure), and otherwise having \expand@c, \expand@Nc and a few more programming tools for 2e preamble coding.

@FrankMittelbach
Copy link
Member

FrankMittelbach commented Dec 16, 2021

\NewDocumentCommand\newcopyedit{mO{red}}
  {%
   \newcounter{todo#1}%                           % declare counter for bookmark
   \ExpandNc\NewDocumentCommand{#1}{s m}          % declare copyedit cmd
     {\IfBooleanTF {##1}%
         {\todo[color=#2!10]{##2}}
         {\todo[inline,color=#2!10]{##2}}%
    \addbookmark{todo#1}{#1}%
   } %
}

\newcopyedit{UFi}[blue]   \newcopyedit{FMi}

@davidcarlisle
Copy link
Member

davidcarlisle commented Dec 16, 2021

searching tex.sx for \expandafter\newcommand\csname (ignoring other similar variants) has almost 3000 hits. Some of them may be in contexts where @ is a letter but a lot are not. Also not always constructing a csname from a surrounding macro argument, sometimes just using fixed but not catcode 11 strings

\expandafter\renewcommand\csname arraytest1 \endcsname

for example.

Some things would be better done in a package or done with expl3 but there is always pressure to do a certain amount of simple programming in the document preamble and I think this could help improve the facilities available for that.

@blefloch
Copy link
Member

Thanks Frank, this is a very clear and compelling use case, I'm now convinced that \ExpandNc makes sense at the document level. I don't know if it should be \expandNc or \ExpandNc but that's quite minor.

@FrankMittelbach
Copy link
Member

Well, all our interface (newer) command \IfBooleanTF, etc are all CamelCase so I tend to think \ExpandNc and \Expandc is fine.

@car222222
Copy link
Contributor

Since we seem recently to have got very close to this, maybe it is simplest to take the logical step of just providing a single very general interface command, thus:

\ExpArgs {}

Maybe particular cases, such as @nameuse, will additionally need simple commands (with clear/useful names:-).

@car222222
Copy link
Contributor

car222222 commented Dec 17, 2021

More precisely:

\ExpArgs {<arg expansion spec>}

@FrankMittelbach
Copy link
Member

As in \def\ExpArgs#1{\csname exp_args:#1\endcsname} ? Or with the first N implicit? The down side of this is slowdown and missing error handling or further slow down.

@blefloch
Copy link
Member

For now I think it is better to stick with just a few commands. If we find ourselves adding more, we can revisit the idea of adding a general \ExpArgs, probably with error checking.

@Skillmon
Copy link
Contributor

Skillmon commented Dec 17, 2021

One could, when you want to add the general \ExpArgs interface, test for \cs_if_exist_use:cF { exp_args: #1 } and build the ::<expansion form> list in the false branch.

@FrankMittelbach
Copy link
Member

@Skillmon but thats what I meant it has a runtime cost instead of a static cost. I'm with @blefloch to just provide the two for now and thats it.

@Skillmon
Copy link
Contributor

Yes, that's correct. But every interface build with \NewDocumentCommand has a lot of runtime cost... But I'm with @blefloch as well :)

@FrankMittelbach
Copy link
Member

I'm not concerned about the few case in front of \NewDocumentCommand. I'm concerned with a general use in other places, e.g., as a replacement of \@nameuse. But anyway, we all seem to say the same thing ... start with the two only

@car222222
Copy link
Contributor

Yes, as I at least meant to say, some commonly used special cases need to be reasonably fast.

I'm not concerned about the few case in front of \NewDocumentCommand.
Aha, OK! So now we know.

I'm concerned with a general use in other places, e.g., as a replacement of @nameuse.

For these a general constructor would be best: then programmers can easily define any such, speedy, command that they need (using whatever name they want!).
Construction of the speedy version of @nameuse can then be given as an example of this methodology.

But anyway, we all seem to say the same thing ... start with the two only

Yes, Maybe two such examples for now, if that is what is supported by the evidence of current common usage.

@car222222
Copy link
Contributor

Eight years old . . . wow!

@FrankMittelbach
Copy link
Member

I'm not concerned about the few case in front of \NewDocumentCommand.
Aha, OK! So now we know.

with respect to speed .. what's so surprising about that?

and what is this line on eight years old? that looks totally out of context.

@FrankMittelbach
Copy link
Member

For these a general constructor would be best: then programmers can easily define any such, speedy, command that they need (using whatever name they want!).
Construction of the speedy version of @nameuse can then be given as an example of this methodology.

I don't really see a good reason for reimplementing the L3 programming layer in 2e. It is all there already: if you write new code and want to make use of all that use L3 prog layer aka expl3.

The suggestion to provide just the two stems from the fact that a) those two are likely to be useful in simple 2e preamble code (that neither wants \makeatletter nor \ExplSyntaxOn or worse a mix of both and b) it is what you find in current 2e style coding 1000+ times. You don't find the full power of expl3 there, because in that style it wasn't really feasible. And I think for "programming" we should stick to L3 programming layer promotion and not attempt to retrofit it to provide "new" functionality in 2e style.

@car222222
Copy link
Contributor

No! Well, I am totally lost now.

No reimplementation was intended.

Look at the whole issue for the 8 years.

@FrankMittelbach
Copy link
Member

As discussed elsewhere we provide four CamelCase commands \Expandc, \ExpandNc,\ExpandNcc, and \ExpandNNc for use in places such as \ExpandNcc\NewDocumentCommand or \Expandc{thecounter#1}which cover the typical use cases with light programming in the preamble. People that need more complicated code need switch to the L3 programming layer, but most situations the above will be sufficient.

@blefloch
Copy link
Member

blefloch commented Jan 2, 2022

Sorry to comment rather than writing a commit, but: we should document \ExpandNc near the \DeclareDocumentCommand documentation.

@FrankMittelbach
Copy link
Member

@blefloch isn't that the way it is is usrguide3.pdf?

  • Creating document commands and environments (covers \NewDocumentCommand etc)
  • Copying and showing (robust) commands (covers \NewCommandCopyetc)
  • Preconstructing command names (covers how to use \ExpandNc etc together with commands from the previous two sections)

@blefloch
Copy link
Member

blefloch commented Jan 2, 2022 via email

@FrankMittelbach
Copy link
Member

Ok, it sounds perfect! I hadn't looked, sorry. Perhaps a note in the documentation of \NewDocumentCommand and the like?

there should remain a reason to buy TLC3 :-) ... but no, you are right, one could and probably should make a forward reference from section 2 to 4. I'll take a look.

@FrankMittelbach
Copy link
Member

@blefloch please take a look at latex3/latex2e@cdc831c to see if this fits the bill

@blefloch
Copy link
Member

blefloch commented Jan 3, 2022 via email

@blefloch
Copy link
Member

blefloch commented Jan 3, 2022 via email

@josephwright
Copy link
Member

Perhaps I'm late to the party, but would \ExpandArgs{Nc}, etc., be better? It would be slower (and need a test for the underlying \exp_args:N..), but would mean that we are only adding one command, and avoid in particular the lack of a 'marker' at the start of the argument list in \Expandc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request xparse Historical: see latex3/latex2e
Projects
None yet
Development

No branches or pull requests