Commands that may take a variable number of argumentsA command with a variable number of arguments: comma versus andHow to print `n` arguments in a command?Cunning (La)TeX tricksUnderstanding @ifnextcharHow to create new commands with multiple arguments?Aligning tikz nodes to tabular cells?Expl3 syntax: graceful handing of conditional/undefined argumentsconvert macro from preamble into a cls fileHow to add numbers with character?DeclareMathOperator won't take argumentsCommand with variable number of arguments to format menu sequencesnewcommand with variable number of argumentsUsing mathpalette with macros that take more argumentsDefining a macro with a variable number of argumentsVariable number of arguments for newcommandLaTeX newcommand with a variable number of argumentsVariable number of arguments in a commanddefine variable with multiple argumentsVariable arguments with `@ifnextchar`

Why Were Madagascar and New Zealand Discovered So Late?

Applicability of Single Responsibility Principle

Where does the Z80 processor start executing from?

Escape a backup date in a file name

Risk of infection at the gym?

Closest Prime Number

Type int? vs type int

Is the destination of a commercial flight important for the pilot?

Two monoidal structures and copowering

Pole-zeros of a real-valued causal FIR system

Was Spock the First Vulcan in Starfleet?

Proof of work - lottery approach

For a non-Jew, is there a punishment for not observing the 7 Noahide Laws?

How does it work when somebody invests in my business?

I'm in charge of equipment buying but no one's ever happy with what I choose. How to fix this?

Term for the "extreme-extension" version of a straw man fallacy?

How can I get through very long and very dry, but also very useful technical documents when learning a new tool?

How does buying out courses with grant money work?

How does Loki do this?

A particular customize with green line and letters for subfloat

How long to clear the 'suck zone' of a turbofan after start is initiated?

What is paid subscription needed for in Mortal Kombat 11?

How do we know the LHC results are robust?

Customer Requests (Sometimes) Drive Me Bonkers!



Commands that may take a variable number of arguments


A command with a variable number of arguments: comma versus andHow to print `n` arguments in a command?Cunning (La)TeX tricksUnderstanding @ifnextcharHow to create new commands with multiple arguments?Aligning tikz nodes to tabular cells?Expl3 syntax: graceful handing of conditional/undefined argumentsconvert macro from preamble into a cls fileHow to add numbers with character?DeclareMathOperator won't take argumentsCommand with variable number of arguments to format menu sequencesnewcommand with variable number of argumentsUsing mathpalette with macros that take more argumentsDefining a macro with a variable number of argumentsVariable number of arguments for newcommandLaTeX newcommand with a variable number of argumentsVariable number of arguments in a commanddefine variable with multiple argumentsVariable arguments with `@ifnextchar`













15















I have a situation where I want to define a command that takes a variable number of arguments, where the number of arguments is known programmatically via a count, and process the parameters in some way (say as if they are a list).



As an example, say I'd like to output the parameters as a comma-separated list.



newcommandmakecsv[N]#1, #2, ..., #N


The code that I've come up with to do this kind of operation (in a generic-ish way) essentially takes a command, csv and expands it recursively N times. csv needs to know how to continue the recursion, and has some state that I'd like to thread through the recursion (rather than using global).



documentclassreport
usepackageetoolbox

makeatletter
newcommandifzero[3]%
% #1: count
% #2: state for #3
% #3: macro to expand to
% - should take at least 2 parameters
% - ##1: count threaded through
% - ##2: macro state threaded through
ifnumc > 0
deftmp@f##1##2##3##1##2##3%
advance#1 -1%
else
deftmp@f##1##2##3)% note closeparen here (could be param)
fi
tmp@f#3#1#2%

makeatother

newcommandcsv[3]
% #1: count
% #2: separator state
% #3: string to concat
%
#2#3ifzero#1, csv%


newcommandmakecsv[1]%
ifzero#1csv%


makeatletter
newcommanddecl[3]%
% #1: decl id
% #2: decl symbol
% #3: # params
csgdefdecl@#1#2%
globalexpandafternewcountcsname decl@#1@nparamsendcsname%
csusedecl@#1@nparams #3relax%


newcommandusedecl[1]%
newcountc
c thecsusedecl@#1@nparams
csusedecl@#1(makecsvc%

makeatother

% declare some interface routines
declfooFOO3
declbarBAR4

begindocument
usedeclfoop1p2p3par
usedeclbarp1p2p3p4par
enddocument


Is this a reasonable thing to do in 2e, or is there some sort of standard approach to this that is normally used?



Edit 1



It seems like my original MWE wasn't adequate to describe why someone might want this. I've updated the MWE with a use case. decl allows authors to declaratively define a C-style function, and usedecl allows the author to generate a use of the function, with its parameters bound to specific arguments.



This is similar enough to what I'm doing that it should help motivate the example.










share|improve this question
























  • You are asking for a list. I think you can search TeX.SX to find a lot of examples. Related packages are etoolbox or l3clist.

    – Marco Daniel
    Jun 7 '13 at 16:42











  • @Marco, I don't think that I'm asking for a list directly. I'm more interested in the technique for writing a command that can process a variable number of arguments. I can't control the source directly, so I can't change foobarfoobar to bar. I do see how I could solve this problem somewhat generically with a list though, with a generic makelistfromargslistnamecounter that reads a bunch of arguments into an internal list. Is this the more common solution that you see people doing?

    – Luke
    Jun 7 '13 at 16:54












  • Perhaps it's easier for us if you provide an aim.

    – Marco Daniel
    Jun 7 '13 at 17:39











  • I can't understand the role of the counter here; what if your counter is set to 2 and you find makecsvcabcdefghi?

    – egreg
    Jun 7 '13 at 18:06











  • Is there a reason you're not considering using keys?

    – A.Ellett
    Jun 7 '13 at 18:31















15















I have a situation where I want to define a command that takes a variable number of arguments, where the number of arguments is known programmatically via a count, and process the parameters in some way (say as if they are a list).



As an example, say I'd like to output the parameters as a comma-separated list.



newcommandmakecsv[N]#1, #2, ..., #N


The code that I've come up with to do this kind of operation (in a generic-ish way) essentially takes a command, csv and expands it recursively N times. csv needs to know how to continue the recursion, and has some state that I'd like to thread through the recursion (rather than using global).



documentclassreport
usepackageetoolbox

makeatletter
newcommandifzero[3]%
% #1: count
% #2: state for #3
% #3: macro to expand to
% - should take at least 2 parameters
% - ##1: count threaded through
% - ##2: macro state threaded through
ifnumc > 0
deftmp@f##1##2##3##1##2##3%
advance#1 -1%
else
deftmp@f##1##2##3)% note closeparen here (could be param)
fi
tmp@f#3#1#2%

makeatother

newcommandcsv[3]
% #1: count
% #2: separator state
% #3: string to concat
%
#2#3ifzero#1, csv%


newcommandmakecsv[1]%
ifzero#1csv%


makeatletter
newcommanddecl[3]%
% #1: decl id
% #2: decl symbol
% #3: # params
csgdefdecl@#1#2%
globalexpandafternewcountcsname decl@#1@nparamsendcsname%
csusedecl@#1@nparams #3relax%


newcommandusedecl[1]%
newcountc
c thecsusedecl@#1@nparams
csusedecl@#1(makecsvc%

makeatother

% declare some interface routines
declfooFOO3
declbarBAR4

begindocument
usedeclfoop1p2p3par
usedeclbarp1p2p3p4par
enddocument


Is this a reasonable thing to do in 2e, or is there some sort of standard approach to this that is normally used?



Edit 1



It seems like my original MWE wasn't adequate to describe why someone might want this. I've updated the MWE with a use case. decl allows authors to declaratively define a C-style function, and usedecl allows the author to generate a use of the function, with its parameters bound to specific arguments.



This is similar enough to what I'm doing that it should help motivate the example.










share|improve this question
























  • You are asking for a list. I think you can search TeX.SX to find a lot of examples. Related packages are etoolbox or l3clist.

    – Marco Daniel
    Jun 7 '13 at 16:42











  • @Marco, I don't think that I'm asking for a list directly. I'm more interested in the technique for writing a command that can process a variable number of arguments. I can't control the source directly, so I can't change foobarfoobar to bar. I do see how I could solve this problem somewhat generically with a list though, with a generic makelistfromargslistnamecounter that reads a bunch of arguments into an internal list. Is this the more common solution that you see people doing?

    – Luke
    Jun 7 '13 at 16:54












  • Perhaps it's easier for us if you provide an aim.

    – Marco Daniel
    Jun 7 '13 at 17:39











  • I can't understand the role of the counter here; what if your counter is set to 2 and you find makecsvcabcdefghi?

    – egreg
    Jun 7 '13 at 18:06











  • Is there a reason you're not considering using keys?

    – A.Ellett
    Jun 7 '13 at 18:31













15












15








15


5






I have a situation where I want to define a command that takes a variable number of arguments, where the number of arguments is known programmatically via a count, and process the parameters in some way (say as if they are a list).



As an example, say I'd like to output the parameters as a comma-separated list.



newcommandmakecsv[N]#1, #2, ..., #N


The code that I've come up with to do this kind of operation (in a generic-ish way) essentially takes a command, csv and expands it recursively N times. csv needs to know how to continue the recursion, and has some state that I'd like to thread through the recursion (rather than using global).



documentclassreport
usepackageetoolbox

makeatletter
newcommandifzero[3]%
% #1: count
% #2: state for #3
% #3: macro to expand to
% - should take at least 2 parameters
% - ##1: count threaded through
% - ##2: macro state threaded through
ifnumc > 0
deftmp@f##1##2##3##1##2##3%
advance#1 -1%
else
deftmp@f##1##2##3)% note closeparen here (could be param)
fi
tmp@f#3#1#2%

makeatother

newcommandcsv[3]
% #1: count
% #2: separator state
% #3: string to concat
%
#2#3ifzero#1, csv%


newcommandmakecsv[1]%
ifzero#1csv%


makeatletter
newcommanddecl[3]%
% #1: decl id
% #2: decl symbol
% #3: # params
csgdefdecl@#1#2%
globalexpandafternewcountcsname decl@#1@nparamsendcsname%
csusedecl@#1@nparams #3relax%


newcommandusedecl[1]%
newcountc
c thecsusedecl@#1@nparams
csusedecl@#1(makecsvc%

makeatother

% declare some interface routines
declfooFOO3
declbarBAR4

begindocument
usedeclfoop1p2p3par
usedeclbarp1p2p3p4par
enddocument


Is this a reasonable thing to do in 2e, or is there some sort of standard approach to this that is normally used?



Edit 1



It seems like my original MWE wasn't adequate to describe why someone might want this. I've updated the MWE with a use case. decl allows authors to declaratively define a C-style function, and usedecl allows the author to generate a use of the function, with its parameters bound to specific arguments.



This is similar enough to what I'm doing that it should help motivate the example.










share|improve this question
















I have a situation where I want to define a command that takes a variable number of arguments, where the number of arguments is known programmatically via a count, and process the parameters in some way (say as if they are a list).



As an example, say I'd like to output the parameters as a comma-separated list.



newcommandmakecsv[N]#1, #2, ..., #N


The code that I've come up with to do this kind of operation (in a generic-ish way) essentially takes a command, csv and expands it recursively N times. csv needs to know how to continue the recursion, and has some state that I'd like to thread through the recursion (rather than using global).



documentclassreport
usepackageetoolbox

makeatletter
newcommandifzero[3]%
% #1: count
% #2: state for #3
% #3: macro to expand to
% - should take at least 2 parameters
% - ##1: count threaded through
% - ##2: macro state threaded through
ifnumc > 0
deftmp@f##1##2##3##1##2##3%
advance#1 -1%
else
deftmp@f##1##2##3)% note closeparen here (could be param)
fi
tmp@f#3#1#2%

makeatother

newcommandcsv[3]
% #1: count
% #2: separator state
% #3: string to concat
%
#2#3ifzero#1, csv%


newcommandmakecsv[1]%
ifzero#1csv%


makeatletter
newcommanddecl[3]%
% #1: decl id
% #2: decl symbol
% #3: # params
csgdefdecl@#1#2%
globalexpandafternewcountcsname decl@#1@nparamsendcsname%
csusedecl@#1@nparams #3relax%


newcommandusedecl[1]%
newcountc
c thecsusedecl@#1@nparams
csusedecl@#1(makecsvc%

makeatother

% declare some interface routines
declfooFOO3
declbarBAR4

begindocument
usedeclfoop1p2p3par
usedeclbarp1p2p3p4par
enddocument


Is this a reasonable thing to do in 2e, or is there some sort of standard approach to this that is normally used?



Edit 1



It seems like my original MWE wasn't adequate to describe why someone might want this. I've updated the MWE with a use case. decl allows authors to declaratively define a C-style function, and usedecl allows the author to generate a use of the function, with its parameters bound to specific arguments.



This is similar enough to what I'm doing that it should help motivate the example.







macros recursion






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jun 7 '13 at 19:07







Luke

















asked Jun 7 '13 at 16:26









LukeLuke

12717




12717












  • You are asking for a list. I think you can search TeX.SX to find a lot of examples. Related packages are etoolbox or l3clist.

    – Marco Daniel
    Jun 7 '13 at 16:42











  • @Marco, I don't think that I'm asking for a list directly. I'm more interested in the technique for writing a command that can process a variable number of arguments. I can't control the source directly, so I can't change foobarfoobar to bar. I do see how I could solve this problem somewhat generically with a list though, with a generic makelistfromargslistnamecounter that reads a bunch of arguments into an internal list. Is this the more common solution that you see people doing?

    – Luke
    Jun 7 '13 at 16:54












  • Perhaps it's easier for us if you provide an aim.

    – Marco Daniel
    Jun 7 '13 at 17:39











  • I can't understand the role of the counter here; what if your counter is set to 2 and you find makecsvcabcdefghi?

    – egreg
    Jun 7 '13 at 18:06











  • Is there a reason you're not considering using keys?

    – A.Ellett
    Jun 7 '13 at 18:31

















  • You are asking for a list. I think you can search TeX.SX to find a lot of examples. Related packages are etoolbox or l3clist.

    – Marco Daniel
    Jun 7 '13 at 16:42











  • @Marco, I don't think that I'm asking for a list directly. I'm more interested in the technique for writing a command that can process a variable number of arguments. I can't control the source directly, so I can't change foobarfoobar to bar. I do see how I could solve this problem somewhat generically with a list though, with a generic makelistfromargslistnamecounter that reads a bunch of arguments into an internal list. Is this the more common solution that you see people doing?

    – Luke
    Jun 7 '13 at 16:54












  • Perhaps it's easier for us if you provide an aim.

    – Marco Daniel
    Jun 7 '13 at 17:39











  • I can't understand the role of the counter here; what if your counter is set to 2 and you find makecsvcabcdefghi?

    – egreg
    Jun 7 '13 at 18:06











  • Is there a reason you're not considering using keys?

    – A.Ellett
    Jun 7 '13 at 18:31
















You are asking for a list. I think you can search TeX.SX to find a lot of examples. Related packages are etoolbox or l3clist.

– Marco Daniel
Jun 7 '13 at 16:42





You are asking for a list. I think you can search TeX.SX to find a lot of examples. Related packages are etoolbox or l3clist.

– Marco Daniel
Jun 7 '13 at 16:42













@Marco, I don't think that I'm asking for a list directly. I'm more interested in the technique for writing a command that can process a variable number of arguments. I can't control the source directly, so I can't change foobarfoobar to bar. I do see how I could solve this problem somewhat generically with a list though, with a generic makelistfromargslistnamecounter that reads a bunch of arguments into an internal list. Is this the more common solution that you see people doing?

– Luke
Jun 7 '13 at 16:54






@Marco, I don't think that I'm asking for a list directly. I'm more interested in the technique for writing a command that can process a variable number of arguments. I can't control the source directly, so I can't change foobarfoobar to bar. I do see how I could solve this problem somewhat generically with a list though, with a generic makelistfromargslistnamecounter that reads a bunch of arguments into an internal list. Is this the more common solution that you see people doing?

– Luke
Jun 7 '13 at 16:54














Perhaps it's easier for us if you provide an aim.

– Marco Daniel
Jun 7 '13 at 17:39





Perhaps it's easier for us if you provide an aim.

– Marco Daniel
Jun 7 '13 at 17:39













I can't understand the role of the counter here; what if your counter is set to 2 and you find makecsvcabcdefghi?

– egreg
Jun 7 '13 at 18:06





I can't understand the role of the counter here; what if your counter is set to 2 and you find makecsvcabcdefghi?

– egreg
Jun 7 '13 at 18:06













Is there a reason you're not considering using keys?

– A.Ellett
Jun 7 '13 at 18:31





Is there a reason you're not considering using keys?

– A.Ellett
Jun 7 '13 at 18:31










4 Answers
4






active

oldest

votes


















8














As commented, here a solution that uses @ifnextchar. I also implemented checks against too many or too few arguments (or why are they provided by the user?).



The @ifnextchar(or its “very internal” big brother kernel@ifnextchar) skips spaces which results in removed spaces in the third and fourth example.



Code



documentclassreport
usepackageetoolbox
makeatletter
newcommand*decl[3]%
% #1: decl id
% #2: decl symbol
% #3: # params
csdefdecl@symbol@#1#2%
expandafternewcountcsname c@decl@params@#1endcsname
csusec@decl@params@#1=#3relax

newcountdecl@params@check
newcommand*usedecl[1]%
defdecl@name#1%
edefdecl@paramsthecsusec@decl@params@#1%
defdecl@symbolcsusedecl@symbol@#1%
decl@params@check=z@
letdecl@list@gobble % the @gobble removes the first , (expandable)
defdecl@nextkernel@ifnextcharbgroupuse@decluse@decl@finish%
decl@next

newcommand*use@decl[1]%
advancedecl@params@check@ne
expandafterifnumthedecl@params@check>decl@paramsrelax % too many!
PackageWarningdeclYou have used more params than the decl@namespace function expected!
I ignore this (and any following) param, ok?% but insert the extra argument anyway?!
defdecl@nextuse@decl@finish#1% the extra pair of braces keeps '#1' local as it is in the input stream
else
expandafterdefexpandafterdecl@listexpandafterdecl@listdecl@list@sep#1%
fi
decl@next

newififuse@decl@message
newcommand*use@decl@finish%
ifnumdecl@params@check<decl@paramsrelax % too few!
expandafter@firstoftwo
else
expandafter@secondoftwo
fi
%
ifuse@decl@messageelse
PackageWarningdeclYou have used fewer params than the decl@namespace function expected! I'm filling up with '??'!%
use@decl@messagetrue
fi
use@decl??
%
decl@symboldecl@list@startdecl@listdecl@list@end
use@decl@messagefalse
%

newcommand*setdeclstart[1]defdecl@list@start#1
newcommand*setdeclend[1]defdecl@list@end#1
newcommand*setdeclsep[1]defdecl@list@sep#1
makeatother

setdeclstart(
setdeclend)
setdeclsep,

% declare some interface routines
declfooFOO3
declbarBAR4

begindocument
given $P$, $Q$ and $R$ such dots that $usedeclfooPQR$ results in dotspar
given P, Q and R such dots that usedeclfooPQR results in dotspar
usedeclfoop1p2p3par
usedeclbarp1p2p3p4par
usedeclbarp1 foopar
usedeclfoop1p2p3 p4par
enddocument


Output



enter image description here






share|improve this answer
































    9














    If you're willing to peek ahead, you can check whether there's "another argument" and keep gobbling them on the fly:



    enter image description here



    documentclassarticle
    usepackageetoolbox% http://ctan.org/pkg/etoolbox

    makeatletter
    newcommandnewdecl[2]csgdefdecl@#1#2% Creates a declaration
    newcommandcsvdel% Delimiter used in CSV representation
    newcommandnewusedecl[2][,]% Use a declaration
    renewcommandcsvdelrenewcommandcsvdel#1,% Delay csvdel one cycle.
    csname decl@#2endcsname(checknextarg
    newcommandchecknextarg@ifnextcharbgroupgobblenext% Check if another "argument" exists
    newcommandgobblenext[1]csvdel#1@ifnextcharbgroupgobblenext)% Gobble next "argument"
    makeatother

    % declare some interface routines
    newdeclfooFOO
    newdeclbarBAR

    begindocument

    newusedeclfoop1p2p3par
    newusedeclbarp1p2p3p4p1p2p3p4p1p2p3p4p1p2p3p4
    p1p2p3p4par
    newusedecl[;]foop1p2p3p4p1p2p3p4p1p2p3p4p1p2p3p4
    p1p2p3p4

    enddocument


    The peeking is done using @ifnextchar. For some explanation around this, see Understanding @ifnextchar. The delayed use of csvdel (the CSV delimiter) stems from Cunning (La)TeX tricks).



    The optional argument to newusedecl adapts csvdel.






    share|improve this answer

























    • Ah, that's nice. So the #1 in gobblenext is the next parameter contents, which I can process as necessary. I think that this is a nice alternative to the way that I'm doing it, but I'm not sure that it's more maintainable than what I've got. I'm going to accept it as an answer and just conclude that this isn't done often enough for there to be a "commonly accepted" pattern.

      – Luke
      Jun 7 '13 at 19:42











    • @Luke: You can adapt the solution to your liking. I'm not entirely sure of your use-case. I've added an optional argument to newusedecl that allows you to update/specify the CSV delimiter. Default is ,.

      – Werner
      Jun 7 '13 at 20:02











    • There is an understandable exampke usage of this idea: davidyat.es/2016/07/27/…. I understood Werner's comments much better after reading that.

      – pauljohn32
      Mar 29 '18 at 9:15


















    3














    You've not given us much to go off of, but here's something that seems to implement what you want while being fed a comma separated list (in lieu of passing a variable number of arguments).



    documentclassarticle
    usepackagexparse
    newcountermyargcounter
    ExplSyntaxOn
    clist_new:N l_myvararg_parameters_clist
    tl_new:N l_myvararg_current_item_tl
    NewDocumentCommandmakecsv m

    clist_set:Nn l_myvararg_parameters_clist #1
    int_while_do:nNnn clist_count:N l_myvararg_parameters_clist > 1

    clist_pop:NN l_myvararg_parameters_clist l_myvararg_current_item_tl
    tl_use:N l_myvararg_current_item_tl,

    clist_pop:NN l_myvararg_parameters_clist
    l_myvararg_current_item_tl
    ~ and ~ tl_use:N l_myvararg_current_item_tl

    ExplSyntaxOff
    pagestyleempty
    begindocument
    makecsva,b,c,d

    makecsva,b,c,d,e,f,g

    makecsva,b

    enddocument





    share|improve this answer























    • Thanks, but as previously stated, I don't have the flexibility to adjust the use-site of makecsv, nor do I want to rely on any non-2e stuff.

      – Luke
      Jun 7 '13 at 19:09











    • I'm not sure I understand what you mean by use-site.

      – A.Ellett
      Jun 7 '13 at 19:26











    • I mean as opposed to definition site. That is, I control the .sty where makecsv it is defined, but I am stuck with the way that .tex authors are already using it. I can't get them to change from makecsvcp1p2p3 to makecsvp1, p2, p3 without a meeting that I don't want to have, since I can actually provide what they want without the API change.

      – Luke
      Jun 7 '13 at 19:33











    • This is a valuable answer! Even though OP cannot use it, readers should not overlook. Similar solution tex.stackexchange.com/questions/417064/…. Only caution: require newer LaTeX distribution

      – pauljohn32
      Mar 29 '18 at 9:22



















    0














    Here is an expansion-based implementation where the loop for gathering the parameters is based on romannumeral both for triggering expansion and for keeping track of the amount of parameters that still is to be collected.



    The usedecl-mechanism does without using any count-registers and without whatsoever temporary assignments for carrying out the loop. e-TeX-extensions and whatsoever fancy packages are not needed. ;-)



    Due to romannumeral-expansion usedecl delivers the result after two expansion-steps/after being hit by expandafter twice.



    documentclassreport

    makeatletter
    %%----------------------------------------------------------------------
    %% Form control sequence token from sequence of characters denoting its
    %% name:
    %% UD@name foobar -> foobar
    %% , e.g.,
    %% UD@namenewcommand*foo -> newcommand*foo
    %% UD@namestringfoo -> stringfoo
    %% UD@nameUD@nameletfoo=bar -> UD@nameletfoo=bar -> letfoo=bar
    %% UD@namefoo -> foo
    %%......................................................................
    @ifdefinableUD@name%
    longdefUD@name#1#romannumeral0UD@innername#1%
    %
    newcommandUD@innername[2]%
    expandafterUD@exchangeexpandaftercsname#2endcsname #1%
    %
    newcommandUD@exchange[2]#2#1%
    %%----------------------------------------------------------------------
    %% Check whether argument is empty:
    %%......................................................................
    %% UD@CheckWhetherNull<Argument which is to be checked>%
    %% <Tokens to be delivered in case that argument
    %% which is to be checked is empty>%
    %% <Tokens to be delivered in case that argument
    %% which is to be checked is not empty>%
    %% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
    %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
    newcommandUD@CheckWhetherNull[1]%
    romannumeral0expandafter@secondoftwostringexpandafter
    @secondoftwoexpandafterexpandafterstring#1expandafter
    @secondoftwostringexpandafter@firstoftwoexpandafterexpandafter
    @secondoftwostringexpandafterexpandafter@firstoftwo %
    @secondoftwoexpandafterexpandafter@firstoftwo @firstoftwo%
    %
    %%----------------------------------------------------------------------
    %% Associate IDs with amounts of parameters and symbols:
    %% No count-registers get allocated/get wasted. Just macros get defined.
    %%......................................................................
    newcommanddecl[3]%
    % #1: decl id; #2: decl symbol; #3: # params
    UD@namenewcommand*decl@#1#2%
    UD@namenewcommand*decl@#1@nparams#3%
    %
    %%----------------------------------------------------------------------
    %% usedecl<decl id><list of parameters of length decl@<decl id>@nparams>
    %%
    %% creates comma list from parameters, nested in parentheses and
    %% lead by the tokens that come from expanding decl@<decl id>
    %%
    %% Due to romannumeral-expansion the result is delivered after two
    %% expansion-steps/after "hitting" usedecl by expandafter twice.
    %%......................................................................
    newcommandusedecl[1]%
    romannumeral0%
    expandafterUD@exchange
    expandafter%
    expandafter%
    romannumeral0%
    UD@exchange UD@nameexpandafterdecl@#1%
    %
    %
    expandafterusedeclloop
    expandafter%
    romannumeralUD@namenumbernumberdecl@#1@nparams 000 %
    %
    %
    %
    newcommandusedeclloop[4]%
    %#1 amount of m = amount of parameters to collect
    %#2 decl symbol
    %#3 prepend-tokens
    %#4 parameters collected so far
    UD@CheckWhetherNull#1 #2(#4)%
    expandafterusedeclloopatfetchexpandafter@gobble#1#2, #4#3%
    %
    %
    newcommandusedeclloopatfetch[5]%
    %#1 amount of m = amount of parameters to collect
    %#2 decl symbol
    %#3 prepend tokens
    %#4 parameters collected so far
    %#5 next parameter fetched.
    usedeclloop#1#2#3#4#5%
    %
    newcommandwithoutdecl[2]%
    romannumeral0%
    expandafterusedeclloopexpandafterromannumeralnumbernumber#2 000 #1%
    %
    %

    makeatother

    % declare the symbols and the amounts of parameters:
    declfooFOO3
    declbarBAR4

    begindocument

    usedeclfoop1p2p3par
    usedeclbarp1p2p3p4par
    withoutdeclBAZ5p1p2p3p4p5par

    expandafterexpandafterexpandafterdef
    expandafterexpandafterexpandafterfoolist
    expandafterexpandafterexpandafter%
    usedeclfoop1p2p3%
    %

    expandafterexpandafterexpandafterdef
    expandafterexpandafterexpandafterbarlist
    expandafterexpandafterexpandafter%
    usedeclbarp1p2p3p4%
    %

    expandafterexpandafterexpandafterdef
    expandafterexpandafterexpandafterbazlist
    expandafterexpandafterexpandafter%
    withoutdeclBAZ5p1p2p3p4p5%
    %

    texttt

    texttt

    texttt

    enddocument


    enter image description here






    share|improve this answer






















      Your Answer








      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "85"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f118114%2fcommands-that-may-take-a-variable-number-of-arguments%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      8














      As commented, here a solution that uses @ifnextchar. I also implemented checks against too many or too few arguments (or why are they provided by the user?).



      The @ifnextchar(or its “very internal” big brother kernel@ifnextchar) skips spaces which results in removed spaces in the third and fourth example.



      Code



      documentclassreport
      usepackageetoolbox
      makeatletter
      newcommand*decl[3]%
      % #1: decl id
      % #2: decl symbol
      % #3: # params
      csdefdecl@symbol@#1#2%
      expandafternewcountcsname c@decl@params@#1endcsname
      csusec@decl@params@#1=#3relax

      newcountdecl@params@check
      newcommand*usedecl[1]%
      defdecl@name#1%
      edefdecl@paramsthecsusec@decl@params@#1%
      defdecl@symbolcsusedecl@symbol@#1%
      decl@params@check=z@
      letdecl@list@gobble % the @gobble removes the first , (expandable)
      defdecl@nextkernel@ifnextcharbgroupuse@decluse@decl@finish%
      decl@next

      newcommand*use@decl[1]%
      advancedecl@params@check@ne
      expandafterifnumthedecl@params@check>decl@paramsrelax % too many!
      PackageWarningdeclYou have used more params than the decl@namespace function expected!
      I ignore this (and any following) param, ok?% but insert the extra argument anyway?!
      defdecl@nextuse@decl@finish#1% the extra pair of braces keeps '#1' local as it is in the input stream
      else
      expandafterdefexpandafterdecl@listexpandafterdecl@listdecl@list@sep#1%
      fi
      decl@next

      newififuse@decl@message
      newcommand*use@decl@finish%
      ifnumdecl@params@check<decl@paramsrelax % too few!
      expandafter@firstoftwo
      else
      expandafter@secondoftwo
      fi
      %
      ifuse@decl@messageelse
      PackageWarningdeclYou have used fewer params than the decl@namespace function expected! I'm filling up with '??'!%
      use@decl@messagetrue
      fi
      use@decl??
      %
      decl@symboldecl@list@startdecl@listdecl@list@end
      use@decl@messagefalse
      %

      newcommand*setdeclstart[1]defdecl@list@start#1
      newcommand*setdeclend[1]defdecl@list@end#1
      newcommand*setdeclsep[1]defdecl@list@sep#1
      makeatother

      setdeclstart(
      setdeclend)
      setdeclsep,

      % declare some interface routines
      declfooFOO3
      declbarBAR4

      begindocument
      given $P$, $Q$ and $R$ such dots that $usedeclfooPQR$ results in dotspar
      given P, Q and R such dots that usedeclfooPQR results in dotspar
      usedeclfoop1p2p3par
      usedeclbarp1p2p3p4par
      usedeclbarp1 foopar
      usedeclfoop1p2p3 p4par
      enddocument


      Output



      enter image description here






      share|improve this answer





























        8














        As commented, here a solution that uses @ifnextchar. I also implemented checks against too many or too few arguments (or why are they provided by the user?).



        The @ifnextchar(or its “very internal” big brother kernel@ifnextchar) skips spaces which results in removed spaces in the third and fourth example.



        Code



        documentclassreport
        usepackageetoolbox
        makeatletter
        newcommand*decl[3]%
        % #1: decl id
        % #2: decl symbol
        % #3: # params
        csdefdecl@symbol@#1#2%
        expandafternewcountcsname c@decl@params@#1endcsname
        csusec@decl@params@#1=#3relax

        newcountdecl@params@check
        newcommand*usedecl[1]%
        defdecl@name#1%
        edefdecl@paramsthecsusec@decl@params@#1%
        defdecl@symbolcsusedecl@symbol@#1%
        decl@params@check=z@
        letdecl@list@gobble % the @gobble removes the first , (expandable)
        defdecl@nextkernel@ifnextcharbgroupuse@decluse@decl@finish%
        decl@next

        newcommand*use@decl[1]%
        advancedecl@params@check@ne
        expandafterifnumthedecl@params@check>decl@paramsrelax % too many!
        PackageWarningdeclYou have used more params than the decl@namespace function expected!
        I ignore this (and any following) param, ok?% but insert the extra argument anyway?!
        defdecl@nextuse@decl@finish#1% the extra pair of braces keeps '#1' local as it is in the input stream
        else
        expandafterdefexpandafterdecl@listexpandafterdecl@listdecl@list@sep#1%
        fi
        decl@next

        newififuse@decl@message
        newcommand*use@decl@finish%
        ifnumdecl@params@check<decl@paramsrelax % too few!
        expandafter@firstoftwo
        else
        expandafter@secondoftwo
        fi
        %
        ifuse@decl@messageelse
        PackageWarningdeclYou have used fewer params than the decl@namespace function expected! I'm filling up with '??'!%
        use@decl@messagetrue
        fi
        use@decl??
        %
        decl@symboldecl@list@startdecl@listdecl@list@end
        use@decl@messagefalse
        %

        newcommand*setdeclstart[1]defdecl@list@start#1
        newcommand*setdeclend[1]defdecl@list@end#1
        newcommand*setdeclsep[1]defdecl@list@sep#1
        makeatother

        setdeclstart(
        setdeclend)
        setdeclsep,

        % declare some interface routines
        declfooFOO3
        declbarBAR4

        begindocument
        given $P$, $Q$ and $R$ such dots that $usedeclfooPQR$ results in dotspar
        given P, Q and R such dots that usedeclfooPQR results in dotspar
        usedeclfoop1p2p3par
        usedeclbarp1p2p3p4par
        usedeclbarp1 foopar
        usedeclfoop1p2p3 p4par
        enddocument


        Output



        enter image description here






        share|improve this answer



























          8












          8








          8







          As commented, here a solution that uses @ifnextchar. I also implemented checks against too many or too few arguments (or why are they provided by the user?).



          The @ifnextchar(or its “very internal” big brother kernel@ifnextchar) skips spaces which results in removed spaces in the third and fourth example.



          Code



          documentclassreport
          usepackageetoolbox
          makeatletter
          newcommand*decl[3]%
          % #1: decl id
          % #2: decl symbol
          % #3: # params
          csdefdecl@symbol@#1#2%
          expandafternewcountcsname c@decl@params@#1endcsname
          csusec@decl@params@#1=#3relax

          newcountdecl@params@check
          newcommand*usedecl[1]%
          defdecl@name#1%
          edefdecl@paramsthecsusec@decl@params@#1%
          defdecl@symbolcsusedecl@symbol@#1%
          decl@params@check=z@
          letdecl@list@gobble % the @gobble removes the first , (expandable)
          defdecl@nextkernel@ifnextcharbgroupuse@decluse@decl@finish%
          decl@next

          newcommand*use@decl[1]%
          advancedecl@params@check@ne
          expandafterifnumthedecl@params@check>decl@paramsrelax % too many!
          PackageWarningdeclYou have used more params than the decl@namespace function expected!
          I ignore this (and any following) param, ok?% but insert the extra argument anyway?!
          defdecl@nextuse@decl@finish#1% the extra pair of braces keeps '#1' local as it is in the input stream
          else
          expandafterdefexpandafterdecl@listexpandafterdecl@listdecl@list@sep#1%
          fi
          decl@next

          newififuse@decl@message
          newcommand*use@decl@finish%
          ifnumdecl@params@check<decl@paramsrelax % too few!
          expandafter@firstoftwo
          else
          expandafter@secondoftwo
          fi
          %
          ifuse@decl@messageelse
          PackageWarningdeclYou have used fewer params than the decl@namespace function expected! I'm filling up with '??'!%
          use@decl@messagetrue
          fi
          use@decl??
          %
          decl@symboldecl@list@startdecl@listdecl@list@end
          use@decl@messagefalse
          %

          newcommand*setdeclstart[1]defdecl@list@start#1
          newcommand*setdeclend[1]defdecl@list@end#1
          newcommand*setdeclsep[1]defdecl@list@sep#1
          makeatother

          setdeclstart(
          setdeclend)
          setdeclsep,

          % declare some interface routines
          declfooFOO3
          declbarBAR4

          begindocument
          given $P$, $Q$ and $R$ such dots that $usedeclfooPQR$ results in dotspar
          given P, Q and R such dots that usedeclfooPQR results in dotspar
          usedeclfoop1p2p3par
          usedeclbarp1p2p3p4par
          usedeclbarp1 foopar
          usedeclfoop1p2p3 p4par
          enddocument


          Output



          enter image description here






          share|improve this answer















          As commented, here a solution that uses @ifnextchar. I also implemented checks against too many or too few arguments (or why are they provided by the user?).



          The @ifnextchar(or its “very internal” big brother kernel@ifnextchar) skips spaces which results in removed spaces in the third and fourth example.



          Code



          documentclassreport
          usepackageetoolbox
          makeatletter
          newcommand*decl[3]%
          % #1: decl id
          % #2: decl symbol
          % #3: # params
          csdefdecl@symbol@#1#2%
          expandafternewcountcsname c@decl@params@#1endcsname
          csusec@decl@params@#1=#3relax

          newcountdecl@params@check
          newcommand*usedecl[1]%
          defdecl@name#1%
          edefdecl@paramsthecsusec@decl@params@#1%
          defdecl@symbolcsusedecl@symbol@#1%
          decl@params@check=z@
          letdecl@list@gobble % the @gobble removes the first , (expandable)
          defdecl@nextkernel@ifnextcharbgroupuse@decluse@decl@finish%
          decl@next

          newcommand*use@decl[1]%
          advancedecl@params@check@ne
          expandafterifnumthedecl@params@check>decl@paramsrelax % too many!
          PackageWarningdeclYou have used more params than the decl@namespace function expected!
          I ignore this (and any following) param, ok?% but insert the extra argument anyway?!
          defdecl@nextuse@decl@finish#1% the extra pair of braces keeps '#1' local as it is in the input stream
          else
          expandafterdefexpandafterdecl@listexpandafterdecl@listdecl@list@sep#1%
          fi
          decl@next

          newififuse@decl@message
          newcommand*use@decl@finish%
          ifnumdecl@params@check<decl@paramsrelax % too few!
          expandafter@firstoftwo
          else
          expandafter@secondoftwo
          fi
          %
          ifuse@decl@messageelse
          PackageWarningdeclYou have used fewer params than the decl@namespace function expected! I'm filling up with '??'!%
          use@decl@messagetrue
          fi
          use@decl??
          %
          decl@symboldecl@list@startdecl@listdecl@list@end
          use@decl@messagefalse
          %

          newcommand*setdeclstart[1]defdecl@list@start#1
          newcommand*setdeclend[1]defdecl@list@end#1
          newcommand*setdeclsep[1]defdecl@list@sep#1
          makeatother

          setdeclstart(
          setdeclend)
          setdeclsep,

          % declare some interface routines
          declfooFOO3
          declbarBAR4

          begindocument
          given $P$, $Q$ and $R$ such dots that $usedeclfooPQR$ results in dotspar
          given P, Q and R such dots that usedeclfooPQR results in dotspar
          usedeclfoop1p2p3par
          usedeclbarp1p2p3p4par
          usedeclbarp1 foopar
          usedeclfoop1p2p3 p4par
          enddocument


          Output



          enter image description here







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jun 8 '13 at 1:13

























          answered Jun 7 '13 at 20:02









          QrrbrbirlbelQrrbrbirlbel

          77.9k4184319




          77.9k4184319





















              9














              If you're willing to peek ahead, you can check whether there's "another argument" and keep gobbling them on the fly:



              enter image description here



              documentclassarticle
              usepackageetoolbox% http://ctan.org/pkg/etoolbox

              makeatletter
              newcommandnewdecl[2]csgdefdecl@#1#2% Creates a declaration
              newcommandcsvdel% Delimiter used in CSV representation
              newcommandnewusedecl[2][,]% Use a declaration
              renewcommandcsvdelrenewcommandcsvdel#1,% Delay csvdel one cycle.
              csname decl@#2endcsname(checknextarg
              newcommandchecknextarg@ifnextcharbgroupgobblenext% Check if another "argument" exists
              newcommandgobblenext[1]csvdel#1@ifnextcharbgroupgobblenext)% Gobble next "argument"
              makeatother

              % declare some interface routines
              newdeclfooFOO
              newdeclbarBAR

              begindocument

              newusedeclfoop1p2p3par
              newusedeclbarp1p2p3p4p1p2p3p4p1p2p3p4p1p2p3p4
              p1p2p3p4par
              newusedecl[;]foop1p2p3p4p1p2p3p4p1p2p3p4p1p2p3p4
              p1p2p3p4

              enddocument


              The peeking is done using @ifnextchar. For some explanation around this, see Understanding @ifnextchar. The delayed use of csvdel (the CSV delimiter) stems from Cunning (La)TeX tricks).



              The optional argument to newusedecl adapts csvdel.






              share|improve this answer

























              • Ah, that's nice. So the #1 in gobblenext is the next parameter contents, which I can process as necessary. I think that this is a nice alternative to the way that I'm doing it, but I'm not sure that it's more maintainable than what I've got. I'm going to accept it as an answer and just conclude that this isn't done often enough for there to be a "commonly accepted" pattern.

                – Luke
                Jun 7 '13 at 19:42











              • @Luke: You can adapt the solution to your liking. I'm not entirely sure of your use-case. I've added an optional argument to newusedecl that allows you to update/specify the CSV delimiter. Default is ,.

                – Werner
                Jun 7 '13 at 20:02











              • There is an understandable exampke usage of this idea: davidyat.es/2016/07/27/…. I understood Werner's comments much better after reading that.

                – pauljohn32
                Mar 29 '18 at 9:15















              9














              If you're willing to peek ahead, you can check whether there's "another argument" and keep gobbling them on the fly:



              enter image description here



              documentclassarticle
              usepackageetoolbox% http://ctan.org/pkg/etoolbox

              makeatletter
              newcommandnewdecl[2]csgdefdecl@#1#2% Creates a declaration
              newcommandcsvdel% Delimiter used in CSV representation
              newcommandnewusedecl[2][,]% Use a declaration
              renewcommandcsvdelrenewcommandcsvdel#1,% Delay csvdel one cycle.
              csname decl@#2endcsname(checknextarg
              newcommandchecknextarg@ifnextcharbgroupgobblenext% Check if another "argument" exists
              newcommandgobblenext[1]csvdel#1@ifnextcharbgroupgobblenext)% Gobble next "argument"
              makeatother

              % declare some interface routines
              newdeclfooFOO
              newdeclbarBAR

              begindocument

              newusedeclfoop1p2p3par
              newusedeclbarp1p2p3p4p1p2p3p4p1p2p3p4p1p2p3p4
              p1p2p3p4par
              newusedecl[;]foop1p2p3p4p1p2p3p4p1p2p3p4p1p2p3p4
              p1p2p3p4

              enddocument


              The peeking is done using @ifnextchar. For some explanation around this, see Understanding @ifnextchar. The delayed use of csvdel (the CSV delimiter) stems from Cunning (La)TeX tricks).



              The optional argument to newusedecl adapts csvdel.






              share|improve this answer

























              • Ah, that's nice. So the #1 in gobblenext is the next parameter contents, which I can process as necessary. I think that this is a nice alternative to the way that I'm doing it, but I'm not sure that it's more maintainable than what I've got. I'm going to accept it as an answer and just conclude that this isn't done often enough for there to be a "commonly accepted" pattern.

                – Luke
                Jun 7 '13 at 19:42











              • @Luke: You can adapt the solution to your liking. I'm not entirely sure of your use-case. I've added an optional argument to newusedecl that allows you to update/specify the CSV delimiter. Default is ,.

                – Werner
                Jun 7 '13 at 20:02











              • There is an understandable exampke usage of this idea: davidyat.es/2016/07/27/…. I understood Werner's comments much better after reading that.

                – pauljohn32
                Mar 29 '18 at 9:15













              9












              9








              9







              If you're willing to peek ahead, you can check whether there's "another argument" and keep gobbling them on the fly:



              enter image description here



              documentclassarticle
              usepackageetoolbox% http://ctan.org/pkg/etoolbox

              makeatletter
              newcommandnewdecl[2]csgdefdecl@#1#2% Creates a declaration
              newcommandcsvdel% Delimiter used in CSV representation
              newcommandnewusedecl[2][,]% Use a declaration
              renewcommandcsvdelrenewcommandcsvdel#1,% Delay csvdel one cycle.
              csname decl@#2endcsname(checknextarg
              newcommandchecknextarg@ifnextcharbgroupgobblenext% Check if another "argument" exists
              newcommandgobblenext[1]csvdel#1@ifnextcharbgroupgobblenext)% Gobble next "argument"
              makeatother

              % declare some interface routines
              newdeclfooFOO
              newdeclbarBAR

              begindocument

              newusedeclfoop1p2p3par
              newusedeclbarp1p2p3p4p1p2p3p4p1p2p3p4p1p2p3p4
              p1p2p3p4par
              newusedecl[;]foop1p2p3p4p1p2p3p4p1p2p3p4p1p2p3p4
              p1p2p3p4

              enddocument


              The peeking is done using @ifnextchar. For some explanation around this, see Understanding @ifnextchar. The delayed use of csvdel (the CSV delimiter) stems from Cunning (La)TeX tricks).



              The optional argument to newusedecl adapts csvdel.






              share|improve this answer















              If you're willing to peek ahead, you can check whether there's "another argument" and keep gobbling them on the fly:



              enter image description here



              documentclassarticle
              usepackageetoolbox% http://ctan.org/pkg/etoolbox

              makeatletter
              newcommandnewdecl[2]csgdefdecl@#1#2% Creates a declaration
              newcommandcsvdel% Delimiter used in CSV representation
              newcommandnewusedecl[2][,]% Use a declaration
              renewcommandcsvdelrenewcommandcsvdel#1,% Delay csvdel one cycle.
              csname decl@#2endcsname(checknextarg
              newcommandchecknextarg@ifnextcharbgroupgobblenext% Check if another "argument" exists
              newcommandgobblenext[1]csvdel#1@ifnextcharbgroupgobblenext)% Gobble next "argument"
              makeatother

              % declare some interface routines
              newdeclfooFOO
              newdeclbarBAR

              begindocument

              newusedeclfoop1p2p3par
              newusedeclbarp1p2p3p4p1p2p3p4p1p2p3p4p1p2p3p4
              p1p2p3p4par
              newusedecl[;]foop1p2p3p4p1p2p3p4p1p2p3p4p1p2p3p4
              p1p2p3p4

              enddocument


              The peeking is done using @ifnextchar. For some explanation around this, see Understanding @ifnextchar. The delayed use of csvdel (the CSV delimiter) stems from Cunning (La)TeX tricks).



              The optional argument to newusedecl adapts csvdel.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Apr 13 '17 at 12:35









              Community

              1




              1










              answered Jun 7 '13 at 19:29









              WernerWerner

              449k719941699




              449k719941699












              • Ah, that's nice. So the #1 in gobblenext is the next parameter contents, which I can process as necessary. I think that this is a nice alternative to the way that I'm doing it, but I'm not sure that it's more maintainable than what I've got. I'm going to accept it as an answer and just conclude that this isn't done often enough for there to be a "commonly accepted" pattern.

                – Luke
                Jun 7 '13 at 19:42











              • @Luke: You can adapt the solution to your liking. I'm not entirely sure of your use-case. I've added an optional argument to newusedecl that allows you to update/specify the CSV delimiter. Default is ,.

                – Werner
                Jun 7 '13 at 20:02











              • There is an understandable exampke usage of this idea: davidyat.es/2016/07/27/…. I understood Werner's comments much better after reading that.

                – pauljohn32
                Mar 29 '18 at 9:15

















              • Ah, that's nice. So the #1 in gobblenext is the next parameter contents, which I can process as necessary. I think that this is a nice alternative to the way that I'm doing it, but I'm not sure that it's more maintainable than what I've got. I'm going to accept it as an answer and just conclude that this isn't done often enough for there to be a "commonly accepted" pattern.

                – Luke
                Jun 7 '13 at 19:42











              • @Luke: You can adapt the solution to your liking. I'm not entirely sure of your use-case. I've added an optional argument to newusedecl that allows you to update/specify the CSV delimiter. Default is ,.

                – Werner
                Jun 7 '13 at 20:02











              • There is an understandable exampke usage of this idea: davidyat.es/2016/07/27/…. I understood Werner's comments much better after reading that.

                – pauljohn32
                Mar 29 '18 at 9:15
















              Ah, that's nice. So the #1 in gobblenext is the next parameter contents, which I can process as necessary. I think that this is a nice alternative to the way that I'm doing it, but I'm not sure that it's more maintainable than what I've got. I'm going to accept it as an answer and just conclude that this isn't done often enough for there to be a "commonly accepted" pattern.

              – Luke
              Jun 7 '13 at 19:42





              Ah, that's nice. So the #1 in gobblenext is the next parameter contents, which I can process as necessary. I think that this is a nice alternative to the way that I'm doing it, but I'm not sure that it's more maintainable than what I've got. I'm going to accept it as an answer and just conclude that this isn't done often enough for there to be a "commonly accepted" pattern.

              – Luke
              Jun 7 '13 at 19:42













              @Luke: You can adapt the solution to your liking. I'm not entirely sure of your use-case. I've added an optional argument to newusedecl that allows you to update/specify the CSV delimiter. Default is ,.

              – Werner
              Jun 7 '13 at 20:02





              @Luke: You can adapt the solution to your liking. I'm not entirely sure of your use-case. I've added an optional argument to newusedecl that allows you to update/specify the CSV delimiter. Default is ,.

              – Werner
              Jun 7 '13 at 20:02













              There is an understandable exampke usage of this idea: davidyat.es/2016/07/27/…. I understood Werner's comments much better after reading that.

              – pauljohn32
              Mar 29 '18 at 9:15





              There is an understandable exampke usage of this idea: davidyat.es/2016/07/27/…. I understood Werner's comments much better after reading that.

              – pauljohn32
              Mar 29 '18 at 9:15











              3














              You've not given us much to go off of, but here's something that seems to implement what you want while being fed a comma separated list (in lieu of passing a variable number of arguments).



              documentclassarticle
              usepackagexparse
              newcountermyargcounter
              ExplSyntaxOn
              clist_new:N l_myvararg_parameters_clist
              tl_new:N l_myvararg_current_item_tl
              NewDocumentCommandmakecsv m

              clist_set:Nn l_myvararg_parameters_clist #1
              int_while_do:nNnn clist_count:N l_myvararg_parameters_clist > 1

              clist_pop:NN l_myvararg_parameters_clist l_myvararg_current_item_tl
              tl_use:N l_myvararg_current_item_tl,

              clist_pop:NN l_myvararg_parameters_clist
              l_myvararg_current_item_tl
              ~ and ~ tl_use:N l_myvararg_current_item_tl

              ExplSyntaxOff
              pagestyleempty
              begindocument
              makecsva,b,c,d

              makecsva,b,c,d,e,f,g

              makecsva,b

              enddocument





              share|improve this answer























              • Thanks, but as previously stated, I don't have the flexibility to adjust the use-site of makecsv, nor do I want to rely on any non-2e stuff.

                – Luke
                Jun 7 '13 at 19:09











              • I'm not sure I understand what you mean by use-site.

                – A.Ellett
                Jun 7 '13 at 19:26











              • I mean as opposed to definition site. That is, I control the .sty where makecsv it is defined, but I am stuck with the way that .tex authors are already using it. I can't get them to change from makecsvcp1p2p3 to makecsvp1, p2, p3 without a meeting that I don't want to have, since I can actually provide what they want without the API change.

                – Luke
                Jun 7 '13 at 19:33











              • This is a valuable answer! Even though OP cannot use it, readers should not overlook. Similar solution tex.stackexchange.com/questions/417064/…. Only caution: require newer LaTeX distribution

                – pauljohn32
                Mar 29 '18 at 9:22
















              3














              You've not given us much to go off of, but here's something that seems to implement what you want while being fed a comma separated list (in lieu of passing a variable number of arguments).



              documentclassarticle
              usepackagexparse
              newcountermyargcounter
              ExplSyntaxOn
              clist_new:N l_myvararg_parameters_clist
              tl_new:N l_myvararg_current_item_tl
              NewDocumentCommandmakecsv m

              clist_set:Nn l_myvararg_parameters_clist #1
              int_while_do:nNnn clist_count:N l_myvararg_parameters_clist > 1

              clist_pop:NN l_myvararg_parameters_clist l_myvararg_current_item_tl
              tl_use:N l_myvararg_current_item_tl,

              clist_pop:NN l_myvararg_parameters_clist
              l_myvararg_current_item_tl
              ~ and ~ tl_use:N l_myvararg_current_item_tl

              ExplSyntaxOff
              pagestyleempty
              begindocument
              makecsva,b,c,d

              makecsva,b,c,d,e,f,g

              makecsva,b

              enddocument





              share|improve this answer























              • Thanks, but as previously stated, I don't have the flexibility to adjust the use-site of makecsv, nor do I want to rely on any non-2e stuff.

                – Luke
                Jun 7 '13 at 19:09











              • I'm not sure I understand what you mean by use-site.

                – A.Ellett
                Jun 7 '13 at 19:26











              • I mean as opposed to definition site. That is, I control the .sty where makecsv it is defined, but I am stuck with the way that .tex authors are already using it. I can't get them to change from makecsvcp1p2p3 to makecsvp1, p2, p3 without a meeting that I don't want to have, since I can actually provide what they want without the API change.

                – Luke
                Jun 7 '13 at 19:33











              • This is a valuable answer! Even though OP cannot use it, readers should not overlook. Similar solution tex.stackexchange.com/questions/417064/…. Only caution: require newer LaTeX distribution

                – pauljohn32
                Mar 29 '18 at 9:22














              3












              3








              3







              You've not given us much to go off of, but here's something that seems to implement what you want while being fed a comma separated list (in lieu of passing a variable number of arguments).



              documentclassarticle
              usepackagexparse
              newcountermyargcounter
              ExplSyntaxOn
              clist_new:N l_myvararg_parameters_clist
              tl_new:N l_myvararg_current_item_tl
              NewDocumentCommandmakecsv m

              clist_set:Nn l_myvararg_parameters_clist #1
              int_while_do:nNnn clist_count:N l_myvararg_parameters_clist > 1

              clist_pop:NN l_myvararg_parameters_clist l_myvararg_current_item_tl
              tl_use:N l_myvararg_current_item_tl,

              clist_pop:NN l_myvararg_parameters_clist
              l_myvararg_current_item_tl
              ~ and ~ tl_use:N l_myvararg_current_item_tl

              ExplSyntaxOff
              pagestyleempty
              begindocument
              makecsva,b,c,d

              makecsva,b,c,d,e,f,g

              makecsva,b

              enddocument





              share|improve this answer













              You've not given us much to go off of, but here's something that seems to implement what you want while being fed a comma separated list (in lieu of passing a variable number of arguments).



              documentclassarticle
              usepackagexparse
              newcountermyargcounter
              ExplSyntaxOn
              clist_new:N l_myvararg_parameters_clist
              tl_new:N l_myvararg_current_item_tl
              NewDocumentCommandmakecsv m

              clist_set:Nn l_myvararg_parameters_clist #1
              int_while_do:nNnn clist_count:N l_myvararg_parameters_clist > 1

              clist_pop:NN l_myvararg_parameters_clist l_myvararg_current_item_tl
              tl_use:N l_myvararg_current_item_tl,

              clist_pop:NN l_myvararg_parameters_clist
              l_myvararg_current_item_tl
              ~ and ~ tl_use:N l_myvararg_current_item_tl

              ExplSyntaxOff
              pagestyleempty
              begindocument
              makecsva,b,c,d

              makecsva,b,c,d,e,f,g

              makecsva,b

              enddocument






              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Jun 7 '13 at 18:59









              A.EllettA.Ellett

              36.6k1169177




              36.6k1169177












              • Thanks, but as previously stated, I don't have the flexibility to adjust the use-site of makecsv, nor do I want to rely on any non-2e stuff.

                – Luke
                Jun 7 '13 at 19:09











              • I'm not sure I understand what you mean by use-site.

                – A.Ellett
                Jun 7 '13 at 19:26











              • I mean as opposed to definition site. That is, I control the .sty where makecsv it is defined, but I am stuck with the way that .tex authors are already using it. I can't get them to change from makecsvcp1p2p3 to makecsvp1, p2, p3 without a meeting that I don't want to have, since I can actually provide what they want without the API change.

                – Luke
                Jun 7 '13 at 19:33











              • This is a valuable answer! Even though OP cannot use it, readers should not overlook. Similar solution tex.stackexchange.com/questions/417064/…. Only caution: require newer LaTeX distribution

                – pauljohn32
                Mar 29 '18 at 9:22


















              • Thanks, but as previously stated, I don't have the flexibility to adjust the use-site of makecsv, nor do I want to rely on any non-2e stuff.

                – Luke
                Jun 7 '13 at 19:09











              • I'm not sure I understand what you mean by use-site.

                – A.Ellett
                Jun 7 '13 at 19:26











              • I mean as opposed to definition site. That is, I control the .sty where makecsv it is defined, but I am stuck with the way that .tex authors are already using it. I can't get them to change from makecsvcp1p2p3 to makecsvp1, p2, p3 without a meeting that I don't want to have, since I can actually provide what they want without the API change.

                – Luke
                Jun 7 '13 at 19:33











              • This is a valuable answer! Even though OP cannot use it, readers should not overlook. Similar solution tex.stackexchange.com/questions/417064/…. Only caution: require newer LaTeX distribution

                – pauljohn32
                Mar 29 '18 at 9:22

















              Thanks, but as previously stated, I don't have the flexibility to adjust the use-site of makecsv, nor do I want to rely on any non-2e stuff.

              – Luke
              Jun 7 '13 at 19:09





              Thanks, but as previously stated, I don't have the flexibility to adjust the use-site of makecsv, nor do I want to rely on any non-2e stuff.

              – Luke
              Jun 7 '13 at 19:09













              I'm not sure I understand what you mean by use-site.

              – A.Ellett
              Jun 7 '13 at 19:26





              I'm not sure I understand what you mean by use-site.

              – A.Ellett
              Jun 7 '13 at 19:26













              I mean as opposed to definition site. That is, I control the .sty where makecsv it is defined, but I am stuck with the way that .tex authors are already using it. I can't get them to change from makecsvcp1p2p3 to makecsvp1, p2, p3 without a meeting that I don't want to have, since I can actually provide what they want without the API change.

              – Luke
              Jun 7 '13 at 19:33





              I mean as opposed to definition site. That is, I control the .sty where makecsv it is defined, but I am stuck with the way that .tex authors are already using it. I can't get them to change from makecsvcp1p2p3 to makecsvp1, p2, p3 without a meeting that I don't want to have, since I can actually provide what they want without the API change.

              – Luke
              Jun 7 '13 at 19:33













              This is a valuable answer! Even though OP cannot use it, readers should not overlook. Similar solution tex.stackexchange.com/questions/417064/…. Only caution: require newer LaTeX distribution

              – pauljohn32
              Mar 29 '18 at 9:22






              This is a valuable answer! Even though OP cannot use it, readers should not overlook. Similar solution tex.stackexchange.com/questions/417064/…. Only caution: require newer LaTeX distribution

              – pauljohn32
              Mar 29 '18 at 9:22












              0














              Here is an expansion-based implementation where the loop for gathering the parameters is based on romannumeral both for triggering expansion and for keeping track of the amount of parameters that still is to be collected.



              The usedecl-mechanism does without using any count-registers and without whatsoever temporary assignments for carrying out the loop. e-TeX-extensions and whatsoever fancy packages are not needed. ;-)



              Due to romannumeral-expansion usedecl delivers the result after two expansion-steps/after being hit by expandafter twice.



              documentclassreport

              makeatletter
              %%----------------------------------------------------------------------
              %% Form control sequence token from sequence of characters denoting its
              %% name:
              %% UD@name foobar -> foobar
              %% , e.g.,
              %% UD@namenewcommand*foo -> newcommand*foo
              %% UD@namestringfoo -> stringfoo
              %% UD@nameUD@nameletfoo=bar -> UD@nameletfoo=bar -> letfoo=bar
              %% UD@namefoo -> foo
              %%......................................................................
              @ifdefinableUD@name%
              longdefUD@name#1#romannumeral0UD@innername#1%
              %
              newcommandUD@innername[2]%
              expandafterUD@exchangeexpandaftercsname#2endcsname #1%
              %
              newcommandUD@exchange[2]#2#1%
              %%----------------------------------------------------------------------
              %% Check whether argument is empty:
              %%......................................................................
              %% UD@CheckWhetherNull<Argument which is to be checked>%
              %% <Tokens to be delivered in case that argument
              %% which is to be checked is empty>%
              %% <Tokens to be delivered in case that argument
              %% which is to be checked is not empty>%
              %% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
              %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
              newcommandUD@CheckWhetherNull[1]%
              romannumeral0expandafter@secondoftwostringexpandafter
              @secondoftwoexpandafterexpandafterstring#1expandafter
              @secondoftwostringexpandafter@firstoftwoexpandafterexpandafter
              @secondoftwostringexpandafterexpandafter@firstoftwo %
              @secondoftwoexpandafterexpandafter@firstoftwo @firstoftwo%
              %
              %%----------------------------------------------------------------------
              %% Associate IDs with amounts of parameters and symbols:
              %% No count-registers get allocated/get wasted. Just macros get defined.
              %%......................................................................
              newcommanddecl[3]%
              % #1: decl id; #2: decl symbol; #3: # params
              UD@namenewcommand*decl@#1#2%
              UD@namenewcommand*decl@#1@nparams#3%
              %
              %%----------------------------------------------------------------------
              %% usedecl<decl id><list of parameters of length decl@<decl id>@nparams>
              %%
              %% creates comma list from parameters, nested in parentheses and
              %% lead by the tokens that come from expanding decl@<decl id>
              %%
              %% Due to romannumeral-expansion the result is delivered after two
              %% expansion-steps/after "hitting" usedecl by expandafter twice.
              %%......................................................................
              newcommandusedecl[1]%
              romannumeral0%
              expandafterUD@exchange
              expandafter%
              expandafter%
              romannumeral0%
              UD@exchange UD@nameexpandafterdecl@#1%
              %
              %
              expandafterusedeclloop
              expandafter%
              romannumeralUD@namenumbernumberdecl@#1@nparams 000 %
              %
              %
              %
              newcommandusedeclloop[4]%
              %#1 amount of m = amount of parameters to collect
              %#2 decl symbol
              %#3 prepend-tokens
              %#4 parameters collected so far
              UD@CheckWhetherNull#1 #2(#4)%
              expandafterusedeclloopatfetchexpandafter@gobble#1#2, #4#3%
              %
              %
              newcommandusedeclloopatfetch[5]%
              %#1 amount of m = amount of parameters to collect
              %#2 decl symbol
              %#3 prepend tokens
              %#4 parameters collected so far
              %#5 next parameter fetched.
              usedeclloop#1#2#3#4#5%
              %
              newcommandwithoutdecl[2]%
              romannumeral0%
              expandafterusedeclloopexpandafterromannumeralnumbernumber#2 000 #1%
              %
              %

              makeatother

              % declare the symbols and the amounts of parameters:
              declfooFOO3
              declbarBAR4

              begindocument

              usedeclfoop1p2p3par
              usedeclbarp1p2p3p4par
              withoutdeclBAZ5p1p2p3p4p5par

              expandafterexpandafterexpandafterdef
              expandafterexpandafterexpandafterfoolist
              expandafterexpandafterexpandafter%
              usedeclfoop1p2p3%
              %

              expandafterexpandafterexpandafterdef
              expandafterexpandafterexpandafterbarlist
              expandafterexpandafterexpandafter%
              usedeclbarp1p2p3p4%
              %

              expandafterexpandafterexpandafterdef
              expandafterexpandafterexpandafterbazlist
              expandafterexpandafterexpandafter%
              withoutdeclBAZ5p1p2p3p4p5%
              %

              texttt

              texttt

              texttt

              enddocument


              enter image description here






              share|improve this answer



























                0














                Here is an expansion-based implementation where the loop for gathering the parameters is based on romannumeral both for triggering expansion and for keeping track of the amount of parameters that still is to be collected.



                The usedecl-mechanism does without using any count-registers and without whatsoever temporary assignments for carrying out the loop. e-TeX-extensions and whatsoever fancy packages are not needed. ;-)



                Due to romannumeral-expansion usedecl delivers the result after two expansion-steps/after being hit by expandafter twice.



                documentclassreport

                makeatletter
                %%----------------------------------------------------------------------
                %% Form control sequence token from sequence of characters denoting its
                %% name:
                %% UD@name foobar -> foobar
                %% , e.g.,
                %% UD@namenewcommand*foo -> newcommand*foo
                %% UD@namestringfoo -> stringfoo
                %% UD@nameUD@nameletfoo=bar -> UD@nameletfoo=bar -> letfoo=bar
                %% UD@namefoo -> foo
                %%......................................................................
                @ifdefinableUD@name%
                longdefUD@name#1#romannumeral0UD@innername#1%
                %
                newcommandUD@innername[2]%
                expandafterUD@exchangeexpandaftercsname#2endcsname #1%
                %
                newcommandUD@exchange[2]#2#1%
                %%----------------------------------------------------------------------
                %% Check whether argument is empty:
                %%......................................................................
                %% UD@CheckWhetherNull<Argument which is to be checked>%
                %% <Tokens to be delivered in case that argument
                %% which is to be checked is empty>%
                %% <Tokens to be delivered in case that argument
                %% which is to be checked is not empty>%
                %% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
                %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
                newcommandUD@CheckWhetherNull[1]%
                romannumeral0expandafter@secondoftwostringexpandafter
                @secondoftwoexpandafterexpandafterstring#1expandafter
                @secondoftwostringexpandafter@firstoftwoexpandafterexpandafter
                @secondoftwostringexpandafterexpandafter@firstoftwo %
                @secondoftwoexpandafterexpandafter@firstoftwo @firstoftwo%
                %
                %%----------------------------------------------------------------------
                %% Associate IDs with amounts of parameters and symbols:
                %% No count-registers get allocated/get wasted. Just macros get defined.
                %%......................................................................
                newcommanddecl[3]%
                % #1: decl id; #2: decl symbol; #3: # params
                UD@namenewcommand*decl@#1#2%
                UD@namenewcommand*decl@#1@nparams#3%
                %
                %%----------------------------------------------------------------------
                %% usedecl<decl id><list of parameters of length decl@<decl id>@nparams>
                %%
                %% creates comma list from parameters, nested in parentheses and
                %% lead by the tokens that come from expanding decl@<decl id>
                %%
                %% Due to romannumeral-expansion the result is delivered after two
                %% expansion-steps/after "hitting" usedecl by expandafter twice.
                %%......................................................................
                newcommandusedecl[1]%
                romannumeral0%
                expandafterUD@exchange
                expandafter%
                expandafter%
                romannumeral0%
                UD@exchange UD@nameexpandafterdecl@#1%
                %
                %
                expandafterusedeclloop
                expandafter%
                romannumeralUD@namenumbernumberdecl@#1@nparams 000 %
                %
                %
                %
                newcommandusedeclloop[4]%
                %#1 amount of m = amount of parameters to collect
                %#2 decl symbol
                %#3 prepend-tokens
                %#4 parameters collected so far
                UD@CheckWhetherNull#1 #2(#4)%
                expandafterusedeclloopatfetchexpandafter@gobble#1#2, #4#3%
                %
                %
                newcommandusedeclloopatfetch[5]%
                %#1 amount of m = amount of parameters to collect
                %#2 decl symbol
                %#3 prepend tokens
                %#4 parameters collected so far
                %#5 next parameter fetched.
                usedeclloop#1#2#3#4#5%
                %
                newcommandwithoutdecl[2]%
                romannumeral0%
                expandafterusedeclloopexpandafterromannumeralnumbernumber#2 000 #1%
                %
                %

                makeatother

                % declare the symbols and the amounts of parameters:
                declfooFOO3
                declbarBAR4

                begindocument

                usedeclfoop1p2p3par
                usedeclbarp1p2p3p4par
                withoutdeclBAZ5p1p2p3p4p5par

                expandafterexpandafterexpandafterdef
                expandafterexpandafterexpandafterfoolist
                expandafterexpandafterexpandafter%
                usedeclfoop1p2p3%
                %

                expandafterexpandafterexpandafterdef
                expandafterexpandafterexpandafterbarlist
                expandafterexpandafterexpandafter%
                usedeclbarp1p2p3p4%
                %

                expandafterexpandafterexpandafterdef
                expandafterexpandafterexpandafterbazlist
                expandafterexpandafterexpandafter%
                withoutdeclBAZ5p1p2p3p4p5%
                %

                texttt

                texttt

                texttt

                enddocument


                enter image description here






                share|improve this answer

























                  0












                  0








                  0







                  Here is an expansion-based implementation where the loop for gathering the parameters is based on romannumeral both for triggering expansion and for keeping track of the amount of parameters that still is to be collected.



                  The usedecl-mechanism does without using any count-registers and without whatsoever temporary assignments for carrying out the loop. e-TeX-extensions and whatsoever fancy packages are not needed. ;-)



                  Due to romannumeral-expansion usedecl delivers the result after two expansion-steps/after being hit by expandafter twice.



                  documentclassreport

                  makeatletter
                  %%----------------------------------------------------------------------
                  %% Form control sequence token from sequence of characters denoting its
                  %% name:
                  %% UD@name foobar -> foobar
                  %% , e.g.,
                  %% UD@namenewcommand*foo -> newcommand*foo
                  %% UD@namestringfoo -> stringfoo
                  %% UD@nameUD@nameletfoo=bar -> UD@nameletfoo=bar -> letfoo=bar
                  %% UD@namefoo -> foo
                  %%......................................................................
                  @ifdefinableUD@name%
                  longdefUD@name#1#romannumeral0UD@innername#1%
                  %
                  newcommandUD@innername[2]%
                  expandafterUD@exchangeexpandaftercsname#2endcsname #1%
                  %
                  newcommandUD@exchange[2]#2#1%
                  %%----------------------------------------------------------------------
                  %% Check whether argument is empty:
                  %%......................................................................
                  %% UD@CheckWhetherNull<Argument which is to be checked>%
                  %% <Tokens to be delivered in case that argument
                  %% which is to be checked is empty>%
                  %% <Tokens to be delivered in case that argument
                  %% which is to be checked is not empty>%
                  %% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
                  %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
                  newcommandUD@CheckWhetherNull[1]%
                  romannumeral0expandafter@secondoftwostringexpandafter
                  @secondoftwoexpandafterexpandafterstring#1expandafter
                  @secondoftwostringexpandafter@firstoftwoexpandafterexpandafter
                  @secondoftwostringexpandafterexpandafter@firstoftwo %
                  @secondoftwoexpandafterexpandafter@firstoftwo @firstoftwo%
                  %
                  %%----------------------------------------------------------------------
                  %% Associate IDs with amounts of parameters and symbols:
                  %% No count-registers get allocated/get wasted. Just macros get defined.
                  %%......................................................................
                  newcommanddecl[3]%
                  % #1: decl id; #2: decl symbol; #3: # params
                  UD@namenewcommand*decl@#1#2%
                  UD@namenewcommand*decl@#1@nparams#3%
                  %
                  %%----------------------------------------------------------------------
                  %% usedecl<decl id><list of parameters of length decl@<decl id>@nparams>
                  %%
                  %% creates comma list from parameters, nested in parentheses and
                  %% lead by the tokens that come from expanding decl@<decl id>
                  %%
                  %% Due to romannumeral-expansion the result is delivered after two
                  %% expansion-steps/after "hitting" usedecl by expandafter twice.
                  %%......................................................................
                  newcommandusedecl[1]%
                  romannumeral0%
                  expandafterUD@exchange
                  expandafter%
                  expandafter%
                  romannumeral0%
                  UD@exchange UD@nameexpandafterdecl@#1%
                  %
                  %
                  expandafterusedeclloop
                  expandafter%
                  romannumeralUD@namenumbernumberdecl@#1@nparams 000 %
                  %
                  %
                  %
                  newcommandusedeclloop[4]%
                  %#1 amount of m = amount of parameters to collect
                  %#2 decl symbol
                  %#3 prepend-tokens
                  %#4 parameters collected so far
                  UD@CheckWhetherNull#1 #2(#4)%
                  expandafterusedeclloopatfetchexpandafter@gobble#1#2, #4#3%
                  %
                  %
                  newcommandusedeclloopatfetch[5]%
                  %#1 amount of m = amount of parameters to collect
                  %#2 decl symbol
                  %#3 prepend tokens
                  %#4 parameters collected so far
                  %#5 next parameter fetched.
                  usedeclloop#1#2#3#4#5%
                  %
                  newcommandwithoutdecl[2]%
                  romannumeral0%
                  expandafterusedeclloopexpandafterromannumeralnumbernumber#2 000 #1%
                  %
                  %

                  makeatother

                  % declare the symbols and the amounts of parameters:
                  declfooFOO3
                  declbarBAR4

                  begindocument

                  usedeclfoop1p2p3par
                  usedeclbarp1p2p3p4par
                  withoutdeclBAZ5p1p2p3p4p5par

                  expandafterexpandafterexpandafterdef
                  expandafterexpandafterexpandafterfoolist
                  expandafterexpandafterexpandafter%
                  usedeclfoop1p2p3%
                  %

                  expandafterexpandafterexpandafterdef
                  expandafterexpandafterexpandafterbarlist
                  expandafterexpandafterexpandafter%
                  usedeclbarp1p2p3p4%
                  %

                  expandafterexpandafterexpandafterdef
                  expandafterexpandafterexpandafterbazlist
                  expandafterexpandafterexpandafter%
                  withoutdeclBAZ5p1p2p3p4p5%
                  %

                  texttt

                  texttt

                  texttt

                  enddocument


                  enter image description here






                  share|improve this answer













                  Here is an expansion-based implementation where the loop for gathering the parameters is based on romannumeral both for triggering expansion and for keeping track of the amount of parameters that still is to be collected.



                  The usedecl-mechanism does without using any count-registers and without whatsoever temporary assignments for carrying out the loop. e-TeX-extensions and whatsoever fancy packages are not needed. ;-)



                  Due to romannumeral-expansion usedecl delivers the result after two expansion-steps/after being hit by expandafter twice.



                  documentclassreport

                  makeatletter
                  %%----------------------------------------------------------------------
                  %% Form control sequence token from sequence of characters denoting its
                  %% name:
                  %% UD@name foobar -> foobar
                  %% , e.g.,
                  %% UD@namenewcommand*foo -> newcommand*foo
                  %% UD@namestringfoo -> stringfoo
                  %% UD@nameUD@nameletfoo=bar -> UD@nameletfoo=bar -> letfoo=bar
                  %% UD@namefoo -> foo
                  %%......................................................................
                  @ifdefinableUD@name%
                  longdefUD@name#1#romannumeral0UD@innername#1%
                  %
                  newcommandUD@innername[2]%
                  expandafterUD@exchangeexpandaftercsname#2endcsname #1%
                  %
                  newcommandUD@exchange[2]#2#1%
                  %%----------------------------------------------------------------------
                  %% Check whether argument is empty:
                  %%......................................................................
                  %% UD@CheckWhetherNull<Argument which is to be checked>%
                  %% <Tokens to be delivered in case that argument
                  %% which is to be checked is empty>%
                  %% <Tokens to be delivered in case that argument
                  %% which is to be checked is not empty>%
                  %% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
                  %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
                  newcommandUD@CheckWhetherNull[1]%
                  romannumeral0expandafter@secondoftwostringexpandafter
                  @secondoftwoexpandafterexpandafterstring#1expandafter
                  @secondoftwostringexpandafter@firstoftwoexpandafterexpandafter
                  @secondoftwostringexpandafterexpandafter@firstoftwo %
                  @secondoftwoexpandafterexpandafter@firstoftwo @firstoftwo%
                  %
                  %%----------------------------------------------------------------------
                  %% Associate IDs with amounts of parameters and symbols:
                  %% No count-registers get allocated/get wasted. Just macros get defined.
                  %%......................................................................
                  newcommanddecl[3]%
                  % #1: decl id; #2: decl symbol; #3: # params
                  UD@namenewcommand*decl@#1#2%
                  UD@namenewcommand*decl@#1@nparams#3%
                  %
                  %%----------------------------------------------------------------------
                  %% usedecl<decl id><list of parameters of length decl@<decl id>@nparams>
                  %%
                  %% creates comma list from parameters, nested in parentheses and
                  %% lead by the tokens that come from expanding decl@<decl id>
                  %%
                  %% Due to romannumeral-expansion the result is delivered after two
                  %% expansion-steps/after "hitting" usedecl by expandafter twice.
                  %%......................................................................
                  newcommandusedecl[1]%
                  romannumeral0%
                  expandafterUD@exchange
                  expandafter%
                  expandafter%
                  romannumeral0%
                  UD@exchange UD@nameexpandafterdecl@#1%
                  %
                  %
                  expandafterusedeclloop
                  expandafter%
                  romannumeralUD@namenumbernumberdecl@#1@nparams 000 %
                  %
                  %
                  %
                  newcommandusedeclloop[4]%
                  %#1 amount of m = amount of parameters to collect
                  %#2 decl symbol
                  %#3 prepend-tokens
                  %#4 parameters collected so far
                  UD@CheckWhetherNull#1 #2(#4)%
                  expandafterusedeclloopatfetchexpandafter@gobble#1#2, #4#3%
                  %
                  %
                  newcommandusedeclloopatfetch[5]%
                  %#1 amount of m = amount of parameters to collect
                  %#2 decl symbol
                  %#3 prepend tokens
                  %#4 parameters collected so far
                  %#5 next parameter fetched.
                  usedeclloop#1#2#3#4#5%
                  %
                  newcommandwithoutdecl[2]%
                  romannumeral0%
                  expandafterusedeclloopexpandafterromannumeralnumbernumber#2 000 #1%
                  %
                  %

                  makeatother

                  % declare the symbols and the amounts of parameters:
                  declfooFOO3
                  declbarBAR4

                  begindocument

                  usedeclfoop1p2p3par
                  usedeclbarp1p2p3p4par
                  withoutdeclBAZ5p1p2p3p4p5par

                  expandafterexpandafterexpandafterdef
                  expandafterexpandafterexpandafterfoolist
                  expandafterexpandafterexpandafter%
                  usedeclfoop1p2p3%
                  %

                  expandafterexpandafterexpandafterdef
                  expandafterexpandafterexpandafterbarlist
                  expandafterexpandafterexpandafter%
                  usedeclbarp1p2p3p4%
                  %

                  expandafterexpandafterexpandafterdef
                  expandafterexpandafterexpandafterbazlist
                  expandafterexpandafterexpandafter%
                  withoutdeclBAZ5p1p2p3p4p5%
                  %

                  texttt

                  texttt

                  texttt

                  enddocument


                  enter image description here







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 22 mins ago









                  Ulrich DiezUlrich Diez

                  5,520620




                  5,520620



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to TeX - LaTeX Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f118114%2fcommands-that-may-take-a-variable-number-of-arguments%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      How should I use the fbox command correctly to avoid producing a Bad Box message?How to put a long piece of text in a box?How to specify height and width of fboxIs there an arrayrulecolor-like command to change the rule color of fbox?What is the command to highlight bad boxes in pdf?Why does fbox sometimes place the box *over* the graphic image?how to put the text in the boxHow to create command for a box where text inside the box can automatically adjust?how can I make an fbox like command with certain color, shape and width of border?how to use fbox in align modeFbox increase the spacing between the box and it content (inner margin)how to change the box height of an equationWhat is the use of the hbox in a newcommand command?

                      152 Atala Notae | Nexus externi | Tabula navigationis"Discovery Circumstances: Numbered Minor Planets"2000152Small-Body Database

                      Doxepinum Nexus interni Notae | Tabula navigationis3158DB01142WHOa682390"Structural Analysis of the Histamine H1 Receptor""Transdermal and Topical Drug Administration in the Treatment of Pain""Antidepressants as antipruritic agents: A review"