Changing the effect of a command in another











up vote
2
down vote

favorite












I'm currently trying to define commands such that:



x{F}{a} gives F^{(x=a)}
y{F}{b} gives F^{(y=b)}


This I can do fairly easily:



newcommand{x}[2]{ensuremath{{#1}^{(x={#2})}}}


However, I would like to have



x{y{F}{b}}{a} gives F^{(y=b, x=a)}


And this, I am currently not able to do.



In practice, I have many such commands x, y, z, ... and I would like to be able to automatically combine them intelligently such that there is only one superscript (see example).



Does anyone know of a way to do this in TeX?










share|improve this question




















  • 1




    That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
    – Skillmon
    Dec 4 at 13:54










  • The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
    – Serker
    Dec 4 at 14:07















up vote
2
down vote

favorite












I'm currently trying to define commands such that:



x{F}{a} gives F^{(x=a)}
y{F}{b} gives F^{(y=b)}


This I can do fairly easily:



newcommand{x}[2]{ensuremath{{#1}^{(x={#2})}}}


However, I would like to have



x{y{F}{b}}{a} gives F^{(y=b, x=a)}


And this, I am currently not able to do.



In practice, I have many such commands x, y, z, ... and I would like to be able to automatically combine them intelligently such that there is only one superscript (see example).



Does anyone know of a way to do this in TeX?










share|improve this question




















  • 1




    That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
    – Skillmon
    Dec 4 at 13:54










  • The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
    – Serker
    Dec 4 at 14:07













up vote
2
down vote

favorite









up vote
2
down vote

favorite











I'm currently trying to define commands such that:



x{F}{a} gives F^{(x=a)}
y{F}{b} gives F^{(y=b)}


This I can do fairly easily:



newcommand{x}[2]{ensuremath{{#1}^{(x={#2})}}}


However, I would like to have



x{y{F}{b}}{a} gives F^{(y=b, x=a)}


And this, I am currently not able to do.



In practice, I have many such commands x, y, z, ... and I would like to be able to automatically combine them intelligently such that there is only one superscript (see example).



Does anyone know of a way to do this in TeX?










share|improve this question















I'm currently trying to define commands such that:



x{F}{a} gives F^{(x=a)}
y{F}{b} gives F^{(y=b)}


This I can do fairly easily:



newcommand{x}[2]{ensuremath{{#1}^{(x={#2})}}}


However, I would like to have



x{y{F}{b}}{a} gives F^{(y=b, x=a)}


And this, I am currently not able to do.



In practice, I have many such commands x, y, z, ... and I would like to be able to automatically combine them intelligently such that there is only one superscript (see example).



Does anyone know of a way to do this in TeX?







macros superscripts






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 6 at 6:04









siracusa

4,76011128




4,76011128










asked Dec 4 at 13:48









Serker

132




132








  • 1




    That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
    – Skillmon
    Dec 4 at 13:54










  • The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
    – Serker
    Dec 4 at 14:07














  • 1




    That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
    – Skillmon
    Dec 4 at 13:54










  • The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
    – Serker
    Dec 4 at 14:07








1




1




That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
– Skillmon
Dec 4 at 13:54




That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
– Skillmon
Dec 4 at 13:54












The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
– Serker
Dec 4 at 14:07




The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
– Serker
Dec 4 at 14:07










4 Answers
4






active

oldest

votes

















up vote
3
down vote



accepted










Have fun with it. Nested use is only correctly handled in the first argument of x, y etc. Create other macros with newtransformation<name>{symbol}.



documentclass{article}

usepackage{amsmath}

newcommandnewtransformation[2]%>>>
{%
newcommand*#1{Fof{#2}}%
}%<<<
makeatletter
defq@stop{q@stop}
longdefafterfi#1fi{fi#1}
newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpandedexpandafter{Fof@pairs{#1}{#3}}}%
#2%
}%<<<
newcommandFof@printpair[3]%>>>
{%
#1=#2%
ifxq@stop#3%
else
afterfi, Fof@printpair{#3}%
fi
}%<<<
newcommand*Fof@printpairs%>>>
{%
expandafterFof@printpairFof@pairsq@stop
}%<<<
newcommand*Fof@output%>>>
{%
Fof@second^{(Fof@printpairs)}%
}%<<<
newcommandFof[3]%>>>
{%
gdefFof@pairs{{#1}{#3}}%
gdefFof@second{#2}%
setboxz@hbox
{% code analog to mathaccentV from amsmath
letFofFof@test
letuse@mathgroup@gobbletwo
letselect@group@gobblethree
frozen@everymath{}%
$#2$%
}%
Fof@output
}%<<<
makeatother

newtransformationx{x}
newtransformationy{y}

begin{document}
$x{y{F}{c}}{b}$
end{document}


enter image description here



To invert the order, you'd have to make sure that the new pairs are added to the front of Fof@pairs. This can be done by changing the definition of Fof@test. Change its definition to the following:



newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpanded{{#1}{#3}}unexpandedexpandafter{Fof@pairs}}%
#2%
}%<<<





share|improve this answer























  • Impressive code, I think it is intended for only two variables? $q{x{y{F}{c}}{b}}{a}$ doesn't seem to work (outputs ! Double superscript).
    – Marijn
    Dec 4 at 14:25










  • @Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
    – Skillmon
    Dec 4 at 14:29










  • @Marijn found the issue, forgot a #2. Should now work fine.
    – Skillmon
    Dec 4 at 14:31










  • it does work now :)
    – Marijn
    Dec 4 at 14:33










  • This is really impressive, I'll try and figure the code out but it works really well, thank you !
    – Serker
    Dec 4 at 14:43


















up vote
4
down vote













Here's a way you could define these transformations.



I defined a macro addtransform that normally just prints {#1}^{#2}, but if it used inside the first argument of another addtransform it'll instead prepend #2, to the list of things to be placed in the superscript of the outermost addtransform (and then print #1). (I hope that makes sense…)



The comments in the code below might be clearer.



documentclass{article}

letcurrtransformempty
newcommand*addtransform[2]{%
ifxcurrtransformempty %% <- if we are not inside an addtransform…
gdefcurrtransform{#2}% %% <- start a list of superscripts
{#1}^{(currtransform)}% %% <- output (N.B. #1 may change currtransform!)
globalletcurrtransformempty %% <- clear the list
else %% <- otherwise…
xdefcurrtransform{unexpanded{#2},% %% <- prepend #2 and a comma
unexpandedexpandafter{currtransform}}%
#1% %% <- then print #1
fi
}

newcommand*transx[2]{addtransform{#1}{x=#2}}
newcommand*transy[2]{addtransform{#1}{y=#2}}
newcommand*transz[2]{addtransform{#1}{z=#2}}

begin{document}

[
transx{F}{a},
qquad
transx{transy{F}{b}}{a},
qquad
transx{transy{transz{F}{c}}{b}}{a}
]

end{document}


output






share|improve this answer























  • Very elegant and simple, +1. Mine is overly complicated because it actually does everything your else branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
    – Skillmon
    Dec 4 at 18:57




















up vote
1
down vote













The syntax you propose is very complicated to maintain, perhaps a simpler one such as



transform{x=a,y=b,z=c}{F}


is better. So I propose an implementation along this line (the argument is then printed from right to left), but also a rewriting of Circumscribe's very fine answer in expl3.



documentclass{article}
usepackage{xparse}

ExplSyntaxOn

% simpler
NewDocumentCommand{transform}{mm}
{
seq_set_from_clist:Nn l_tmpa_seq { #1 }
seq_reverse:N l_tmpa_seq
#2^{ ( seq_use:Nn l_tmpa_seq {,} ) }
}

% recursive
NewDocumentCommand{definetransform}{m}
{
clist_map_inline:nn { #1 }
{
cs_new_protected:cpn { ##1 } ####1 ####2
{
serker_transform:nnn { ##1 } { ####1 } { ####2 }
}
}
}

seq_new:N g__serker_transform_seq

cs_new_protected:Nn serker_transform:nnn
{
seq_if_empty:NTF g__serker_transform_seq
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
{#2}^{ ( seq_use:Nn g__serker_transform_seq {,} ) }
seq_gclear:N g__serker_transform_seq
}
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
#2
}
}

ExplSyntaxOff

definetransform{x,y,z} % add to the list

begin{document}

[
transform{x=a}{F},
qquad
transform{x=a,y=b}{F},
qquad
transform{x=a,y=b,z=c}{F}
]

[
x{F}{a},
qquad
x{y{F}{b}}{a},
qquad
x{y{z{F}{c}}{b}}{a}
]

end{document}


enter image description here






share|improve this answer




























    up vote
    1
    down vote













    documentclass{article}
    makeatletter
    %%----------------------------------------------------------------------
    %% Paraphernalia
    %%----------------------------------------------------------------------
    newcommandUD@firstoftwo[2]{#1}%
    newcommandUD@secondoftwo[2]{#2}%
    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>
    %%
    %% (romannumeral expansion was introduced in order to overcome the
    %% concerns and worries about improperly balanced
    %% if..else..fi constructs.)
    %%
    newcommandUD@CheckWhetherNull[1]{%
    romannumeral0expandafterUD@secondoftwostring{expandafter
    UD@secondoftwoexpandafter{expandafter{string#1}expandafter
    UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
    UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
    UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
    }%
    %%----------------------------------------------------------------------
    %% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
    %% {<Tokens to be delivered in case <argument
    %% which is to be checked>'s 1st token is
    %% UD@CollectMore>}%
    %% {<Tokens to be delivered in case <argument
    %% which is to be checked>'s 1st token is not
    %% UD@CollectMore>}%
    %%----------------------------------------------------------------------
    newcommandUD@CheckWhetherLeadingUD@CollectMore[1]{%
    romannumeral0UD@CheckWhetherNull{#1}%
    {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
    {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingUD@CollectMoreB.#1UD@CollectMore}{}}%
    }%
    newcommandUD@CheckWhetherLeadingUD@CollectMoreB{}%
    longdefUD@CheckWhetherLeadingUD@CollectMoreB#1UD@CollectMore{%
    expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
    {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
    {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
    expandafterexpandafterexpandafter}expandafterexpandafter
    expandafter}expandafterUD@secondoftwoexpandafter{string}%
    }%
    %%......................................................................
    newcommandUD@CollectMore{UD@CollectMore@B{}}%
    newcommandUD@CollectMore@B[3]{%
    expandafterUD@CheckWhetherLeadingUD@CollectMoreexpandafter{#2}{%
    expandafterexpandafterexpandafterUD@Exchange
    expandafterexpandafterexpandafter{%
    expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
    }{%
    ensuremath{{#2}^{(#3#1)}}%
    }%
    }%
    %%......................................................................

    newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
    newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
    newcommandz[2]{UD@CollectMore{#1}{z=#2}}%

    newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
    newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
    newcommandW[2]{UD@CollectMore{#1}{w=#2}}%

    makeatother

    begin{document}

    verb|x{F}{a}|: % yields F^{(x=a)}
    x{F}{a}% gives F^{(x=a)}

    verb|y{F}{b}|: % yields F^{(y=b)}
    y{F}{b}% gives F^{(y=b)}

    verb|z{F}{c}|: % yields F^{(z=b)}
    z{F}{c}% gives F^{(z=b)}

    verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
    x{y{F}{b}}{a}% gives F^{(y=b, x=a)}

    verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
    x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}

    verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
    U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}

    end{document}


    enter image description here





    With the example above, the routine for checking for another nested transformation does attempt top-level-expansion to the first token of a transformation-macro's first argument in any case.

    In edge cases this might cause problems.



    The example below includes a checking routine with some brace-hacks which does the check without attempting to top-level-expand the first token of a transformation-macro's first argument and which applies top-level-expansion to that token only in case it is one of the tokens that are used as transformation-macros.



    Advantage:



    This is more safe even in edge cases.



    Disadvantages:



    In case you wish to rename some of the transformation-macros or wish to add some transformation-macros, you need to adjust
    the checking-mechanism (UD@MoreTransformationsFork, UD@@MoreTransformationsFork) as well as it does check on the presence of tokens and not on their meaning.



    The load of code is a bit larger: When grabbing the first token of an argument for checking whether it is either x or y or z or the like, you also need to take into account that the very first token of the argument could as well be a space-token or a curly opening-brace or that the argument might be empty, and as you check on the presence of one of several tokens, you need code for cranking out several cases.



    documentclass{article}
    makeatletter
    %%----------------------------------------------------------------------
    %% Paraphernalia
    %%----------------------------------------------------------------------
    newcommandUD@firstoftwo[2]{#1}%
    newcommandUD@secondoftwo[2]{#2}%
    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]{%
    romannumeral0expandafterUD@secondoftwostring{expandafter
    UD@secondoftwoexpandafter{expandafter{string#1}expandafter
    UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
    UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
    UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
    }%
    %%-----------------------------------------------------------------------------
    %% Check whether argument's first token is a catcode-1-character
    %%.............................................................................
    %% UD@CheckWhetherBrace{<Argument which is to be checked>}%
    %% {<Tokens to be delivered in case that argument
    %% which is to be checked has leading
    %% catcode-1-token>}%
    %% {<Tokens to be delivered in case that argument
    %% which is to be checked has no leading
    %% catcode-1-token>}%
    newcommandUD@CheckWhetherBrace[1]{%
    romannumeral0expandafterUD@secondoftwoexpandafter{expandafter{%
    string#1.}expandafterUD@firstoftwoexpandafter{expandafter
    UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
    UD@firstoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
    }%
    %%==============================================================================
    %% Check whether brace-balanced argument starts with a space-token
    %%..............................................................................
    %% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
    %% {<Tokens to be delivered in case <argument
    %% which is to be checked>'s 1st token is a
    %% space-token>}%
    %% {<Tokens to be delivered in case <argument
    %% which is to be checked>'s 1st token is not
    %% a space-token>}%
    newcommandUD@CheckWhetherLeadingSpace[1]{%
    romannumeral0UD@CheckWhetherNull{#1}%
    {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
    {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
    }%
    newcommandUD@CheckWhetherLeadingSpaceB{}%
    longdefUD@CheckWhetherLeadingSpaceB#1 {%
    expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
    {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
    {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
    expandafterexpandafterexpandafter}expandafterexpandafter
    expandafter}expandafterUD@secondoftwoexpandafter{string}%
    }%
    %%-----------------------------------------------------------------------------
    %% Check whether argument does not contain "!":
    %%.............................................................................
    newcommandUD@GobbleToExclam{}%
    longdefUD@GobbleToExclam#1!{}%
    newcommandUD@CheckWhetherNoExclam[1]{%
    expandafterUD@CheckWhetherNullexpandafter{UD@GobbleToExclam#1!}%
    }%
    %%----------------------------------------------------------------------
    %% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
    %% {<Tokens to be delivered in case <argument
    %% which is to be checked>'s 1st token is
    %% UD@CollectMore>}%
    %% {<Tokens to be delivered in case <argument
    %% which is to be checked>'s 1st token is not
    %% UD@CollectMore>}%
    %%----------------------------------------------------------------------
    newcommandUD@CheckForMoreTransformations[1]{%
    romannumeral0UD@CheckWhetherBrace{#1}{%
    expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
    }{%
    UD@CheckWhetherLeadingSpace{#1}{%
    expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
    }{%
    UD@CheckWhetherNull{#1}{%
    expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
    }{%
    expandafterUD@secondoftwostring{UD@MoreTransformationsFork#1}{}%
    }%
    }%
    }%
    }%
    newcommandUD@MoreTransformationsFork[1]{%
    UD@CheckWhetherNoExclam{#1}{%
    UD@@MoreTransformationsFork!#1!V!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% U
    !U!#1!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% V
    !U!V!#1!x!y!z!{UD@Exchange{UD@firstoftwo}}% W
    !U!V!W!#1!y!z!{UD@Exchange{UD@firstoftwo}}% x
    !U!V!W!x!#1!z!{UD@Exchange{UD@firstoftwo}}% y
    !U!V!W!x!y!#1!{UD@Exchange{UD@firstoftwo}}% z
    !U!V!W!x!y!z!{UD@Exchange{UD@secondoftwo}}% something else without !
    !!!!%
    }{UD@Exchange{UD@secondoftwo}}% something else with !
    {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
    expandafterexpandafterexpandafter}expandafterexpandafter
    expandafter}expandafterUD@secondoftwoexpandafter{string}%
    }%
    newcommandUD@@MoreTransformationsFork{}%
    longdefUD@@MoreTransformationsFork#1!U!V!W!x!y!z!#2#3!!!!{#2}%
    %%......................................................................
    newcommandUD@CollectMore{UD@CollectMore@B{}}%
    newcommandUD@CollectMore@B[3]{%
    UD@CheckForMoreTransformations{#2}{%
    expandafterexpandafterexpandafterUD@Exchange
    expandafterexpandafterexpandafter{%
    expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
    }{%
    ensuremath{{#2}^{(#3#1)}}%
    }%
    }%
    %%......................................................................

    newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
    newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
    newcommandz[2]{UD@CollectMore{#1}{z=#2}}%

    newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
    newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
    newcommandW[2]{UD@CollectMore{#1}{w=#2}}%

    makeatother

    begin{document}

    verb|x{F}{a}|: % yields F^{(x=a)}
    x{F}{a}% gives F^{(x=a)}

    verb|y{F}{b}|: % yields F^{(y=b)}
    y{F}{b}% gives F^{(y=b)}

    verb|z{F}{c}|: % yields F^{(z=b)}
    z{F}{c}% gives F^{(z=b)}

    verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
    x{y{F}{b}}{a}% gives F^{(y=b, x=a)}

    verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
    x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}

    verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
    U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}

    end{document}


    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',
      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%2f463149%2fchanging-the-effect-of-a-command-in-another%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








      up vote
      3
      down vote



      accepted










      Have fun with it. Nested use is only correctly handled in the first argument of x, y etc. Create other macros with newtransformation<name>{symbol}.



      documentclass{article}

      usepackage{amsmath}

      newcommandnewtransformation[2]%>>>
      {%
      newcommand*#1{Fof{#2}}%
      }%<<<
      makeatletter
      defq@stop{q@stop}
      longdefafterfi#1fi{fi#1}
      newcommandFof@test[3]%>>>
      {%
      gdefFof@second{#2}%
      xdefFof@pairs{unexpandedexpandafter{Fof@pairs{#1}{#3}}}%
      #2%
      }%<<<
      newcommandFof@printpair[3]%>>>
      {%
      #1=#2%
      ifxq@stop#3%
      else
      afterfi, Fof@printpair{#3}%
      fi
      }%<<<
      newcommand*Fof@printpairs%>>>
      {%
      expandafterFof@printpairFof@pairsq@stop
      }%<<<
      newcommand*Fof@output%>>>
      {%
      Fof@second^{(Fof@printpairs)}%
      }%<<<
      newcommandFof[3]%>>>
      {%
      gdefFof@pairs{{#1}{#3}}%
      gdefFof@second{#2}%
      setboxz@hbox
      {% code analog to mathaccentV from amsmath
      letFofFof@test
      letuse@mathgroup@gobbletwo
      letselect@group@gobblethree
      frozen@everymath{}%
      $#2$%
      }%
      Fof@output
      }%<<<
      makeatother

      newtransformationx{x}
      newtransformationy{y}

      begin{document}
      $x{y{F}{c}}{b}$
      end{document}


      enter image description here



      To invert the order, you'd have to make sure that the new pairs are added to the front of Fof@pairs. This can be done by changing the definition of Fof@test. Change its definition to the following:



      newcommandFof@test[3]%>>>
      {%
      gdefFof@second{#2}%
      xdefFof@pairs{unexpanded{{#1}{#3}}unexpandedexpandafter{Fof@pairs}}%
      #2%
      }%<<<





      share|improve this answer























      • Impressive code, I think it is intended for only two variables? $q{x{y{F}{c}}{b}}{a}$ doesn't seem to work (outputs ! Double superscript).
        – Marijn
        Dec 4 at 14:25










      • @Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
        – Skillmon
        Dec 4 at 14:29










      • @Marijn found the issue, forgot a #2. Should now work fine.
        – Skillmon
        Dec 4 at 14:31










      • it does work now :)
        – Marijn
        Dec 4 at 14:33










      • This is really impressive, I'll try and figure the code out but it works really well, thank you !
        – Serker
        Dec 4 at 14:43















      up vote
      3
      down vote



      accepted










      Have fun with it. Nested use is only correctly handled in the first argument of x, y etc. Create other macros with newtransformation<name>{symbol}.



      documentclass{article}

      usepackage{amsmath}

      newcommandnewtransformation[2]%>>>
      {%
      newcommand*#1{Fof{#2}}%
      }%<<<
      makeatletter
      defq@stop{q@stop}
      longdefafterfi#1fi{fi#1}
      newcommandFof@test[3]%>>>
      {%
      gdefFof@second{#2}%
      xdefFof@pairs{unexpandedexpandafter{Fof@pairs{#1}{#3}}}%
      #2%
      }%<<<
      newcommandFof@printpair[3]%>>>
      {%
      #1=#2%
      ifxq@stop#3%
      else
      afterfi, Fof@printpair{#3}%
      fi
      }%<<<
      newcommand*Fof@printpairs%>>>
      {%
      expandafterFof@printpairFof@pairsq@stop
      }%<<<
      newcommand*Fof@output%>>>
      {%
      Fof@second^{(Fof@printpairs)}%
      }%<<<
      newcommandFof[3]%>>>
      {%
      gdefFof@pairs{{#1}{#3}}%
      gdefFof@second{#2}%
      setboxz@hbox
      {% code analog to mathaccentV from amsmath
      letFofFof@test
      letuse@mathgroup@gobbletwo
      letselect@group@gobblethree
      frozen@everymath{}%
      $#2$%
      }%
      Fof@output
      }%<<<
      makeatother

      newtransformationx{x}
      newtransformationy{y}

      begin{document}
      $x{y{F}{c}}{b}$
      end{document}


      enter image description here



      To invert the order, you'd have to make sure that the new pairs are added to the front of Fof@pairs. This can be done by changing the definition of Fof@test. Change its definition to the following:



      newcommandFof@test[3]%>>>
      {%
      gdefFof@second{#2}%
      xdefFof@pairs{unexpanded{{#1}{#3}}unexpandedexpandafter{Fof@pairs}}%
      #2%
      }%<<<





      share|improve this answer























      • Impressive code, I think it is intended for only two variables? $q{x{y{F}{c}}{b}}{a}$ doesn't seem to work (outputs ! Double superscript).
        – Marijn
        Dec 4 at 14:25










      • @Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
        – Skillmon
        Dec 4 at 14:29










      • @Marijn found the issue, forgot a #2. Should now work fine.
        – Skillmon
        Dec 4 at 14:31










      • it does work now :)
        – Marijn
        Dec 4 at 14:33










      • This is really impressive, I'll try and figure the code out but it works really well, thank you !
        – Serker
        Dec 4 at 14:43













      up vote
      3
      down vote



      accepted







      up vote
      3
      down vote



      accepted






      Have fun with it. Nested use is only correctly handled in the first argument of x, y etc. Create other macros with newtransformation<name>{symbol}.



      documentclass{article}

      usepackage{amsmath}

      newcommandnewtransformation[2]%>>>
      {%
      newcommand*#1{Fof{#2}}%
      }%<<<
      makeatletter
      defq@stop{q@stop}
      longdefafterfi#1fi{fi#1}
      newcommandFof@test[3]%>>>
      {%
      gdefFof@second{#2}%
      xdefFof@pairs{unexpandedexpandafter{Fof@pairs{#1}{#3}}}%
      #2%
      }%<<<
      newcommandFof@printpair[3]%>>>
      {%
      #1=#2%
      ifxq@stop#3%
      else
      afterfi, Fof@printpair{#3}%
      fi
      }%<<<
      newcommand*Fof@printpairs%>>>
      {%
      expandafterFof@printpairFof@pairsq@stop
      }%<<<
      newcommand*Fof@output%>>>
      {%
      Fof@second^{(Fof@printpairs)}%
      }%<<<
      newcommandFof[3]%>>>
      {%
      gdefFof@pairs{{#1}{#3}}%
      gdefFof@second{#2}%
      setboxz@hbox
      {% code analog to mathaccentV from amsmath
      letFofFof@test
      letuse@mathgroup@gobbletwo
      letselect@group@gobblethree
      frozen@everymath{}%
      $#2$%
      }%
      Fof@output
      }%<<<
      makeatother

      newtransformationx{x}
      newtransformationy{y}

      begin{document}
      $x{y{F}{c}}{b}$
      end{document}


      enter image description here



      To invert the order, you'd have to make sure that the new pairs are added to the front of Fof@pairs. This can be done by changing the definition of Fof@test. Change its definition to the following:



      newcommandFof@test[3]%>>>
      {%
      gdefFof@second{#2}%
      xdefFof@pairs{unexpanded{{#1}{#3}}unexpandedexpandafter{Fof@pairs}}%
      #2%
      }%<<<





      share|improve this answer














      Have fun with it. Nested use is only correctly handled in the first argument of x, y etc. Create other macros with newtransformation<name>{symbol}.



      documentclass{article}

      usepackage{amsmath}

      newcommandnewtransformation[2]%>>>
      {%
      newcommand*#1{Fof{#2}}%
      }%<<<
      makeatletter
      defq@stop{q@stop}
      longdefafterfi#1fi{fi#1}
      newcommandFof@test[3]%>>>
      {%
      gdefFof@second{#2}%
      xdefFof@pairs{unexpandedexpandafter{Fof@pairs{#1}{#3}}}%
      #2%
      }%<<<
      newcommandFof@printpair[3]%>>>
      {%
      #1=#2%
      ifxq@stop#3%
      else
      afterfi, Fof@printpair{#3}%
      fi
      }%<<<
      newcommand*Fof@printpairs%>>>
      {%
      expandafterFof@printpairFof@pairsq@stop
      }%<<<
      newcommand*Fof@output%>>>
      {%
      Fof@second^{(Fof@printpairs)}%
      }%<<<
      newcommandFof[3]%>>>
      {%
      gdefFof@pairs{{#1}{#3}}%
      gdefFof@second{#2}%
      setboxz@hbox
      {% code analog to mathaccentV from amsmath
      letFofFof@test
      letuse@mathgroup@gobbletwo
      letselect@group@gobblethree
      frozen@everymath{}%
      $#2$%
      }%
      Fof@output
      }%<<<
      makeatother

      newtransformationx{x}
      newtransformationy{y}

      begin{document}
      $x{y{F}{c}}{b}$
      end{document}


      enter image description here



      To invert the order, you'd have to make sure that the new pairs are added to the front of Fof@pairs. This can be done by changing the definition of Fof@test. Change its definition to the following:



      newcommandFof@test[3]%>>>
      {%
      gdefFof@second{#2}%
      xdefFof@pairs{unexpanded{{#1}{#3}}unexpandedexpandafter{Fof@pairs}}%
      #2%
      }%<<<






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Dec 4 at 18:47

























      answered Dec 4 at 14:17









      Skillmon

      20.7k11941




      20.7k11941












      • Impressive code, I think it is intended for only two variables? $q{x{y{F}{c}}{b}}{a}$ doesn't seem to work (outputs ! Double superscript).
        – Marijn
        Dec 4 at 14:25










      • @Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
        – Skillmon
        Dec 4 at 14:29










      • @Marijn found the issue, forgot a #2. Should now work fine.
        – Skillmon
        Dec 4 at 14:31










      • it does work now :)
        – Marijn
        Dec 4 at 14:33










      • This is really impressive, I'll try and figure the code out but it works really well, thank you !
        – Serker
        Dec 4 at 14:43


















      • Impressive code, I think it is intended for only two variables? $q{x{y{F}{c}}{b}}{a}$ doesn't seem to work (outputs ! Double superscript).
        – Marijn
        Dec 4 at 14:25










      • @Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
        – Skillmon
        Dec 4 at 14:29










      • @Marijn found the issue, forgot a #2. Should now work fine.
        – Skillmon
        Dec 4 at 14:31










      • it does work now :)
        – Marijn
        Dec 4 at 14:33










      • This is really impressive, I'll try and figure the code out but it works really well, thank you !
        – Serker
        Dec 4 at 14:43
















      Impressive code, I think it is intended for only two variables? $q{x{y{F}{c}}{b}}{a}$ doesn't seem to work (outputs ! Double superscript).
      – Marijn
      Dec 4 at 14:25




      Impressive code, I think it is intended for only two variables? $q{x{y{F}{c}}{b}}{a}$ doesn't seem to work (outputs ! Double superscript).
      – Marijn
      Dec 4 at 14:25












      @Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
      – Skillmon
      Dec 4 at 14:29




      @Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
      – Skillmon
      Dec 4 at 14:29












      @Marijn found the issue, forgot a #2. Should now work fine.
      – Skillmon
      Dec 4 at 14:31




      @Marijn found the issue, forgot a #2. Should now work fine.
      – Skillmon
      Dec 4 at 14:31












      it does work now :)
      – Marijn
      Dec 4 at 14:33




      it does work now :)
      – Marijn
      Dec 4 at 14:33












      This is really impressive, I'll try and figure the code out but it works really well, thank you !
      – Serker
      Dec 4 at 14:43




      This is really impressive, I'll try and figure the code out but it works really well, thank you !
      – Serker
      Dec 4 at 14:43










      up vote
      4
      down vote













      Here's a way you could define these transformations.



      I defined a macro addtransform that normally just prints {#1}^{#2}, but if it used inside the first argument of another addtransform it'll instead prepend #2, to the list of things to be placed in the superscript of the outermost addtransform (and then print #1). (I hope that makes sense…)



      The comments in the code below might be clearer.



      documentclass{article}

      letcurrtransformempty
      newcommand*addtransform[2]{%
      ifxcurrtransformempty %% <- if we are not inside an addtransform…
      gdefcurrtransform{#2}% %% <- start a list of superscripts
      {#1}^{(currtransform)}% %% <- output (N.B. #1 may change currtransform!)
      globalletcurrtransformempty %% <- clear the list
      else %% <- otherwise…
      xdefcurrtransform{unexpanded{#2},% %% <- prepend #2 and a comma
      unexpandedexpandafter{currtransform}}%
      #1% %% <- then print #1
      fi
      }

      newcommand*transx[2]{addtransform{#1}{x=#2}}
      newcommand*transy[2]{addtransform{#1}{y=#2}}
      newcommand*transz[2]{addtransform{#1}{z=#2}}

      begin{document}

      [
      transx{F}{a},
      qquad
      transx{transy{F}{b}}{a},
      qquad
      transx{transy{transz{F}{c}}{b}}{a}
      ]

      end{document}


      output






      share|improve this answer























      • Very elegant and simple, +1. Mine is overly complicated because it actually does everything your else branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
        – Skillmon
        Dec 4 at 18:57

















      up vote
      4
      down vote













      Here's a way you could define these transformations.



      I defined a macro addtransform that normally just prints {#1}^{#2}, but if it used inside the first argument of another addtransform it'll instead prepend #2, to the list of things to be placed in the superscript of the outermost addtransform (and then print #1). (I hope that makes sense…)



      The comments in the code below might be clearer.



      documentclass{article}

      letcurrtransformempty
      newcommand*addtransform[2]{%
      ifxcurrtransformempty %% <- if we are not inside an addtransform…
      gdefcurrtransform{#2}% %% <- start a list of superscripts
      {#1}^{(currtransform)}% %% <- output (N.B. #1 may change currtransform!)
      globalletcurrtransformempty %% <- clear the list
      else %% <- otherwise…
      xdefcurrtransform{unexpanded{#2},% %% <- prepend #2 and a comma
      unexpandedexpandafter{currtransform}}%
      #1% %% <- then print #1
      fi
      }

      newcommand*transx[2]{addtransform{#1}{x=#2}}
      newcommand*transy[2]{addtransform{#1}{y=#2}}
      newcommand*transz[2]{addtransform{#1}{z=#2}}

      begin{document}

      [
      transx{F}{a},
      qquad
      transx{transy{F}{b}}{a},
      qquad
      transx{transy{transz{F}{c}}{b}}{a}
      ]

      end{document}


      output






      share|improve this answer























      • Very elegant and simple, +1. Mine is overly complicated because it actually does everything your else branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
        – Skillmon
        Dec 4 at 18:57















      up vote
      4
      down vote










      up vote
      4
      down vote









      Here's a way you could define these transformations.



      I defined a macro addtransform that normally just prints {#1}^{#2}, but if it used inside the first argument of another addtransform it'll instead prepend #2, to the list of things to be placed in the superscript of the outermost addtransform (and then print #1). (I hope that makes sense…)



      The comments in the code below might be clearer.



      documentclass{article}

      letcurrtransformempty
      newcommand*addtransform[2]{%
      ifxcurrtransformempty %% <- if we are not inside an addtransform…
      gdefcurrtransform{#2}% %% <- start a list of superscripts
      {#1}^{(currtransform)}% %% <- output (N.B. #1 may change currtransform!)
      globalletcurrtransformempty %% <- clear the list
      else %% <- otherwise…
      xdefcurrtransform{unexpanded{#2},% %% <- prepend #2 and a comma
      unexpandedexpandafter{currtransform}}%
      #1% %% <- then print #1
      fi
      }

      newcommand*transx[2]{addtransform{#1}{x=#2}}
      newcommand*transy[2]{addtransform{#1}{y=#2}}
      newcommand*transz[2]{addtransform{#1}{z=#2}}

      begin{document}

      [
      transx{F}{a},
      qquad
      transx{transy{F}{b}}{a},
      qquad
      transx{transy{transz{F}{c}}{b}}{a}
      ]

      end{document}


      output






      share|improve this answer














      Here's a way you could define these transformations.



      I defined a macro addtransform that normally just prints {#1}^{#2}, but if it used inside the first argument of another addtransform it'll instead prepend #2, to the list of things to be placed in the superscript of the outermost addtransform (and then print #1). (I hope that makes sense…)



      The comments in the code below might be clearer.



      documentclass{article}

      letcurrtransformempty
      newcommand*addtransform[2]{%
      ifxcurrtransformempty %% <- if we are not inside an addtransform…
      gdefcurrtransform{#2}% %% <- start a list of superscripts
      {#1}^{(currtransform)}% %% <- output (N.B. #1 may change currtransform!)
      globalletcurrtransformempty %% <- clear the list
      else %% <- otherwise…
      xdefcurrtransform{unexpanded{#2},% %% <- prepend #2 and a comma
      unexpandedexpandafter{currtransform}}%
      #1% %% <- then print #1
      fi
      }

      newcommand*transx[2]{addtransform{#1}{x=#2}}
      newcommand*transy[2]{addtransform{#1}{y=#2}}
      newcommand*transz[2]{addtransform{#1}{z=#2}}

      begin{document}

      [
      transx{F}{a},
      qquad
      transx{transy{F}{b}}{a},
      qquad
      transx{transy{transz{F}{c}}{b}}{a}
      ]

      end{document}


      output







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Dec 4 at 19:41

























      answered Dec 4 at 18:49









      Circumscribe

      4,2571429




      4,2571429












      • Very elegant and simple, +1. Mine is overly complicated because it actually does everything your else branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
        – Skillmon
        Dec 4 at 18:57




















      • Very elegant and simple, +1. Mine is overly complicated because it actually does everything your else branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
        – Skillmon
        Dec 4 at 18:57


















      Very elegant and simple, +1. Mine is overly complicated because it actually does everything your else branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
      – Skillmon
      Dec 4 at 18:57






      Very elegant and simple, +1. Mine is overly complicated because it actually does everything your else branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
      – Skillmon
      Dec 4 at 18:57












      up vote
      1
      down vote













      The syntax you propose is very complicated to maintain, perhaps a simpler one such as



      transform{x=a,y=b,z=c}{F}


      is better. So I propose an implementation along this line (the argument is then printed from right to left), but also a rewriting of Circumscribe's very fine answer in expl3.



      documentclass{article}
      usepackage{xparse}

      ExplSyntaxOn

      % simpler
      NewDocumentCommand{transform}{mm}
      {
      seq_set_from_clist:Nn l_tmpa_seq { #1 }
      seq_reverse:N l_tmpa_seq
      #2^{ ( seq_use:Nn l_tmpa_seq {,} ) }
      }

      % recursive
      NewDocumentCommand{definetransform}{m}
      {
      clist_map_inline:nn { #1 }
      {
      cs_new_protected:cpn { ##1 } ####1 ####2
      {
      serker_transform:nnn { ##1 } { ####1 } { ####2 }
      }
      }
      }

      seq_new:N g__serker_transform_seq

      cs_new_protected:Nn serker_transform:nnn
      {
      seq_if_empty:NTF g__serker_transform_seq
      {
      seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
      {#2}^{ ( seq_use:Nn g__serker_transform_seq {,} ) }
      seq_gclear:N g__serker_transform_seq
      }
      {
      seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
      #2
      }
      }

      ExplSyntaxOff

      definetransform{x,y,z} % add to the list

      begin{document}

      [
      transform{x=a}{F},
      qquad
      transform{x=a,y=b}{F},
      qquad
      transform{x=a,y=b,z=c}{F}
      ]

      [
      x{F}{a},
      qquad
      x{y{F}{b}}{a},
      qquad
      x{y{z{F}{c}}{b}}{a}
      ]

      end{document}


      enter image description here






      share|improve this answer

























        up vote
        1
        down vote













        The syntax you propose is very complicated to maintain, perhaps a simpler one such as



        transform{x=a,y=b,z=c}{F}


        is better. So I propose an implementation along this line (the argument is then printed from right to left), but also a rewriting of Circumscribe's very fine answer in expl3.



        documentclass{article}
        usepackage{xparse}

        ExplSyntaxOn

        % simpler
        NewDocumentCommand{transform}{mm}
        {
        seq_set_from_clist:Nn l_tmpa_seq { #1 }
        seq_reverse:N l_tmpa_seq
        #2^{ ( seq_use:Nn l_tmpa_seq {,} ) }
        }

        % recursive
        NewDocumentCommand{definetransform}{m}
        {
        clist_map_inline:nn { #1 }
        {
        cs_new_protected:cpn { ##1 } ####1 ####2
        {
        serker_transform:nnn { ##1 } { ####1 } { ####2 }
        }
        }
        }

        seq_new:N g__serker_transform_seq

        cs_new_protected:Nn serker_transform:nnn
        {
        seq_if_empty:NTF g__serker_transform_seq
        {
        seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
        {#2}^{ ( seq_use:Nn g__serker_transform_seq {,} ) }
        seq_gclear:N g__serker_transform_seq
        }
        {
        seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
        #2
        }
        }

        ExplSyntaxOff

        definetransform{x,y,z} % add to the list

        begin{document}

        [
        transform{x=a}{F},
        qquad
        transform{x=a,y=b}{F},
        qquad
        transform{x=a,y=b,z=c}{F}
        ]

        [
        x{F}{a},
        qquad
        x{y{F}{b}}{a},
        qquad
        x{y{z{F}{c}}{b}}{a}
        ]

        end{document}


        enter image description here






        share|improve this answer























          up vote
          1
          down vote










          up vote
          1
          down vote









          The syntax you propose is very complicated to maintain, perhaps a simpler one such as



          transform{x=a,y=b,z=c}{F}


          is better. So I propose an implementation along this line (the argument is then printed from right to left), but also a rewriting of Circumscribe's very fine answer in expl3.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          % simpler
          NewDocumentCommand{transform}{mm}
          {
          seq_set_from_clist:Nn l_tmpa_seq { #1 }
          seq_reverse:N l_tmpa_seq
          #2^{ ( seq_use:Nn l_tmpa_seq {,} ) }
          }

          % recursive
          NewDocumentCommand{definetransform}{m}
          {
          clist_map_inline:nn { #1 }
          {
          cs_new_protected:cpn { ##1 } ####1 ####2
          {
          serker_transform:nnn { ##1 } { ####1 } { ####2 }
          }
          }
          }

          seq_new:N g__serker_transform_seq

          cs_new_protected:Nn serker_transform:nnn
          {
          seq_if_empty:NTF g__serker_transform_seq
          {
          seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
          {#2}^{ ( seq_use:Nn g__serker_transform_seq {,} ) }
          seq_gclear:N g__serker_transform_seq
          }
          {
          seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
          #2
          }
          }

          ExplSyntaxOff

          definetransform{x,y,z} % add to the list

          begin{document}

          [
          transform{x=a}{F},
          qquad
          transform{x=a,y=b}{F},
          qquad
          transform{x=a,y=b,z=c}{F}
          ]

          [
          x{F}{a},
          qquad
          x{y{F}{b}}{a},
          qquad
          x{y{z{F}{c}}{b}}{a}
          ]

          end{document}


          enter image description here






          share|improve this answer












          The syntax you propose is very complicated to maintain, perhaps a simpler one such as



          transform{x=a,y=b,z=c}{F}


          is better. So I propose an implementation along this line (the argument is then printed from right to left), but also a rewriting of Circumscribe's very fine answer in expl3.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          % simpler
          NewDocumentCommand{transform}{mm}
          {
          seq_set_from_clist:Nn l_tmpa_seq { #1 }
          seq_reverse:N l_tmpa_seq
          #2^{ ( seq_use:Nn l_tmpa_seq {,} ) }
          }

          % recursive
          NewDocumentCommand{definetransform}{m}
          {
          clist_map_inline:nn { #1 }
          {
          cs_new_protected:cpn { ##1 } ####1 ####2
          {
          serker_transform:nnn { ##1 } { ####1 } { ####2 }
          }
          }
          }

          seq_new:N g__serker_transform_seq

          cs_new_protected:Nn serker_transform:nnn
          {
          seq_if_empty:NTF g__serker_transform_seq
          {
          seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
          {#2}^{ ( seq_use:Nn g__serker_transform_seq {,} ) }
          seq_gclear:N g__serker_transform_seq
          }
          {
          seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
          #2
          }
          }

          ExplSyntaxOff

          definetransform{x,y,z} % add to the list

          begin{document}

          [
          transform{x=a}{F},
          qquad
          transform{x=a,y=b}{F},
          qquad
          transform{x=a,y=b,z=c}{F}
          ]

          [
          x{F}{a},
          qquad
          x{y{F}{b}}{a},
          qquad
          x{y{z{F}{c}}{b}}{a}
          ]

          end{document}


          enter image description here







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 5 at 13:21









          egreg

          704k8618753154




          704k8618753154






















              up vote
              1
              down vote













              documentclass{article}
              makeatletter
              %%----------------------------------------------------------------------
              %% Paraphernalia
              %%----------------------------------------------------------------------
              newcommandUD@firstoftwo[2]{#1}%
              newcommandUD@secondoftwo[2]{#2}%
              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>
              %%
              %% (romannumeral expansion was introduced in order to overcome the
              %% concerns and worries about improperly balanced
              %% if..else..fi constructs.)
              %%
              newcommandUD@CheckWhetherNull[1]{%
              romannumeral0expandafterUD@secondoftwostring{expandafter
              UD@secondoftwoexpandafter{expandafter{string#1}expandafter
              UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
              UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
              UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
              }%
              %%----------------------------------------------------------------------
              %% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
              %% {<Tokens to be delivered in case <argument
              %% which is to be checked>'s 1st token is
              %% UD@CollectMore>}%
              %% {<Tokens to be delivered in case <argument
              %% which is to be checked>'s 1st token is not
              %% UD@CollectMore>}%
              %%----------------------------------------------------------------------
              newcommandUD@CheckWhetherLeadingUD@CollectMore[1]{%
              romannumeral0UD@CheckWhetherNull{#1}%
              {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
              {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingUD@CollectMoreB.#1UD@CollectMore}{}}%
              }%
              newcommandUD@CheckWhetherLeadingUD@CollectMoreB{}%
              longdefUD@CheckWhetherLeadingUD@CollectMoreB#1UD@CollectMore{%
              expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
              {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
              {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
              expandafterexpandafterexpandafter}expandafterexpandafter
              expandafter}expandafterUD@secondoftwoexpandafter{string}%
              }%
              %%......................................................................
              newcommandUD@CollectMore{UD@CollectMore@B{}}%
              newcommandUD@CollectMore@B[3]{%
              expandafterUD@CheckWhetherLeadingUD@CollectMoreexpandafter{#2}{%
              expandafterexpandafterexpandafterUD@Exchange
              expandafterexpandafterexpandafter{%
              expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
              }{%
              ensuremath{{#2}^{(#3#1)}}%
              }%
              }%
              %%......................................................................

              newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
              newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
              newcommandz[2]{UD@CollectMore{#1}{z=#2}}%

              newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
              newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
              newcommandW[2]{UD@CollectMore{#1}{w=#2}}%

              makeatother

              begin{document}

              verb|x{F}{a}|: % yields F^{(x=a)}
              x{F}{a}% gives F^{(x=a)}

              verb|y{F}{b}|: % yields F^{(y=b)}
              y{F}{b}% gives F^{(y=b)}

              verb|z{F}{c}|: % yields F^{(z=b)}
              z{F}{c}% gives F^{(z=b)}

              verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
              x{y{F}{b}}{a}% gives F^{(y=b, x=a)}

              verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
              x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}

              verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
              U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}

              end{document}


              enter image description here





              With the example above, the routine for checking for another nested transformation does attempt top-level-expansion to the first token of a transformation-macro's first argument in any case.

              In edge cases this might cause problems.



              The example below includes a checking routine with some brace-hacks which does the check without attempting to top-level-expand the first token of a transformation-macro's first argument and which applies top-level-expansion to that token only in case it is one of the tokens that are used as transformation-macros.



              Advantage:



              This is more safe even in edge cases.



              Disadvantages:



              In case you wish to rename some of the transformation-macros or wish to add some transformation-macros, you need to adjust
              the checking-mechanism (UD@MoreTransformationsFork, UD@@MoreTransformationsFork) as well as it does check on the presence of tokens and not on their meaning.



              The load of code is a bit larger: When grabbing the first token of an argument for checking whether it is either x or y or z or the like, you also need to take into account that the very first token of the argument could as well be a space-token or a curly opening-brace or that the argument might be empty, and as you check on the presence of one of several tokens, you need code for cranking out several cases.



              documentclass{article}
              makeatletter
              %%----------------------------------------------------------------------
              %% Paraphernalia
              %%----------------------------------------------------------------------
              newcommandUD@firstoftwo[2]{#1}%
              newcommandUD@secondoftwo[2]{#2}%
              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]{%
              romannumeral0expandafterUD@secondoftwostring{expandafter
              UD@secondoftwoexpandafter{expandafter{string#1}expandafter
              UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
              UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
              UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
              }%
              %%-----------------------------------------------------------------------------
              %% Check whether argument's first token is a catcode-1-character
              %%.............................................................................
              %% UD@CheckWhetherBrace{<Argument which is to be checked>}%
              %% {<Tokens to be delivered in case that argument
              %% which is to be checked has leading
              %% catcode-1-token>}%
              %% {<Tokens to be delivered in case that argument
              %% which is to be checked has no leading
              %% catcode-1-token>}%
              newcommandUD@CheckWhetherBrace[1]{%
              romannumeral0expandafterUD@secondoftwoexpandafter{expandafter{%
              string#1.}expandafterUD@firstoftwoexpandafter{expandafter
              UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
              UD@firstoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
              }%
              %%==============================================================================
              %% Check whether brace-balanced argument starts with a space-token
              %%..............................................................................
              %% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
              %% {<Tokens to be delivered in case <argument
              %% which is to be checked>'s 1st token is a
              %% space-token>}%
              %% {<Tokens to be delivered in case <argument
              %% which is to be checked>'s 1st token is not
              %% a space-token>}%
              newcommandUD@CheckWhetherLeadingSpace[1]{%
              romannumeral0UD@CheckWhetherNull{#1}%
              {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
              {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
              }%
              newcommandUD@CheckWhetherLeadingSpaceB{}%
              longdefUD@CheckWhetherLeadingSpaceB#1 {%
              expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
              {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
              {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
              expandafterexpandafterexpandafter}expandafterexpandafter
              expandafter}expandafterUD@secondoftwoexpandafter{string}%
              }%
              %%-----------------------------------------------------------------------------
              %% Check whether argument does not contain "!":
              %%.............................................................................
              newcommandUD@GobbleToExclam{}%
              longdefUD@GobbleToExclam#1!{}%
              newcommandUD@CheckWhetherNoExclam[1]{%
              expandafterUD@CheckWhetherNullexpandafter{UD@GobbleToExclam#1!}%
              }%
              %%----------------------------------------------------------------------
              %% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
              %% {<Tokens to be delivered in case <argument
              %% which is to be checked>'s 1st token is
              %% UD@CollectMore>}%
              %% {<Tokens to be delivered in case <argument
              %% which is to be checked>'s 1st token is not
              %% UD@CollectMore>}%
              %%----------------------------------------------------------------------
              newcommandUD@CheckForMoreTransformations[1]{%
              romannumeral0UD@CheckWhetherBrace{#1}{%
              expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
              }{%
              UD@CheckWhetherLeadingSpace{#1}{%
              expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
              }{%
              UD@CheckWhetherNull{#1}{%
              expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
              }{%
              expandafterUD@secondoftwostring{UD@MoreTransformationsFork#1}{}%
              }%
              }%
              }%
              }%
              newcommandUD@MoreTransformationsFork[1]{%
              UD@CheckWhetherNoExclam{#1}{%
              UD@@MoreTransformationsFork!#1!V!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% U
              !U!#1!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% V
              !U!V!#1!x!y!z!{UD@Exchange{UD@firstoftwo}}% W
              !U!V!W!#1!y!z!{UD@Exchange{UD@firstoftwo}}% x
              !U!V!W!x!#1!z!{UD@Exchange{UD@firstoftwo}}% y
              !U!V!W!x!y!#1!{UD@Exchange{UD@firstoftwo}}% z
              !U!V!W!x!y!z!{UD@Exchange{UD@secondoftwo}}% something else without !
              !!!!%
              }{UD@Exchange{UD@secondoftwo}}% something else with !
              {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
              expandafterexpandafterexpandafter}expandafterexpandafter
              expandafter}expandafterUD@secondoftwoexpandafter{string}%
              }%
              newcommandUD@@MoreTransformationsFork{}%
              longdefUD@@MoreTransformationsFork#1!U!V!W!x!y!z!#2#3!!!!{#2}%
              %%......................................................................
              newcommandUD@CollectMore{UD@CollectMore@B{}}%
              newcommandUD@CollectMore@B[3]{%
              UD@CheckForMoreTransformations{#2}{%
              expandafterexpandafterexpandafterUD@Exchange
              expandafterexpandafterexpandafter{%
              expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
              }{%
              ensuremath{{#2}^{(#3#1)}}%
              }%
              }%
              %%......................................................................

              newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
              newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
              newcommandz[2]{UD@CollectMore{#1}{z=#2}}%

              newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
              newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
              newcommandW[2]{UD@CollectMore{#1}{w=#2}}%

              makeatother

              begin{document}

              verb|x{F}{a}|: % yields F^{(x=a)}
              x{F}{a}% gives F^{(x=a)}

              verb|y{F}{b}|: % yields F^{(y=b)}
              y{F}{b}% gives F^{(y=b)}

              verb|z{F}{c}|: % yields F^{(z=b)}
              z{F}{c}% gives F^{(z=b)}

              verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
              x{y{F}{b}}{a}% gives F^{(y=b, x=a)}

              verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
              x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}

              verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
              U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}

              end{document}


              enter image description here






              share|improve this answer



























                up vote
                1
                down vote













                documentclass{article}
                makeatletter
                %%----------------------------------------------------------------------
                %% Paraphernalia
                %%----------------------------------------------------------------------
                newcommandUD@firstoftwo[2]{#1}%
                newcommandUD@secondoftwo[2]{#2}%
                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>
                %%
                %% (romannumeral expansion was introduced in order to overcome the
                %% concerns and worries about improperly balanced
                %% if..else..fi constructs.)
                %%
                newcommandUD@CheckWhetherNull[1]{%
                romannumeral0expandafterUD@secondoftwostring{expandafter
                UD@secondoftwoexpandafter{expandafter{string#1}expandafter
                UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
                UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
                }%
                %%----------------------------------------------------------------------
                %% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
                %% {<Tokens to be delivered in case <argument
                %% which is to be checked>'s 1st token is
                %% UD@CollectMore>}%
                %% {<Tokens to be delivered in case <argument
                %% which is to be checked>'s 1st token is not
                %% UD@CollectMore>}%
                %%----------------------------------------------------------------------
                newcommandUD@CheckWhetherLeadingUD@CollectMore[1]{%
                romannumeral0UD@CheckWhetherNull{#1}%
                {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingUD@CollectMoreB.#1UD@CollectMore}{}}%
                }%
                newcommandUD@CheckWhetherLeadingUD@CollectMoreB{}%
                longdefUD@CheckWhetherLeadingUD@CollectMoreB#1UD@CollectMore{%
                expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
                {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
                {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                expandafterexpandafterexpandafter}expandafterexpandafter
                expandafter}expandafterUD@secondoftwoexpandafter{string}%
                }%
                %%......................................................................
                newcommandUD@CollectMore{UD@CollectMore@B{}}%
                newcommandUD@CollectMore@B[3]{%
                expandafterUD@CheckWhetherLeadingUD@CollectMoreexpandafter{#2}{%
                expandafterexpandafterexpandafterUD@Exchange
                expandafterexpandafterexpandafter{%
                expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
                }{%
                ensuremath{{#2}^{(#3#1)}}%
                }%
                }%
                %%......................................................................

                newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
                newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
                newcommandz[2]{UD@CollectMore{#1}{z=#2}}%

                newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
                newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
                newcommandW[2]{UD@CollectMore{#1}{w=#2}}%

                makeatother

                begin{document}

                verb|x{F}{a}|: % yields F^{(x=a)}
                x{F}{a}% gives F^{(x=a)}

                verb|y{F}{b}|: % yields F^{(y=b)}
                y{F}{b}% gives F^{(y=b)}

                verb|z{F}{c}|: % yields F^{(z=b)}
                z{F}{c}% gives F^{(z=b)}

                verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
                x{y{F}{b}}{a}% gives F^{(y=b, x=a)}

                verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
                x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}

                verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
                U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}

                end{document}


                enter image description here





                With the example above, the routine for checking for another nested transformation does attempt top-level-expansion to the first token of a transformation-macro's first argument in any case.

                In edge cases this might cause problems.



                The example below includes a checking routine with some brace-hacks which does the check without attempting to top-level-expand the first token of a transformation-macro's first argument and which applies top-level-expansion to that token only in case it is one of the tokens that are used as transformation-macros.



                Advantage:



                This is more safe even in edge cases.



                Disadvantages:



                In case you wish to rename some of the transformation-macros or wish to add some transformation-macros, you need to adjust
                the checking-mechanism (UD@MoreTransformationsFork, UD@@MoreTransformationsFork) as well as it does check on the presence of tokens and not on their meaning.



                The load of code is a bit larger: When grabbing the first token of an argument for checking whether it is either x or y or z or the like, you also need to take into account that the very first token of the argument could as well be a space-token or a curly opening-brace or that the argument might be empty, and as you check on the presence of one of several tokens, you need code for cranking out several cases.



                documentclass{article}
                makeatletter
                %%----------------------------------------------------------------------
                %% Paraphernalia
                %%----------------------------------------------------------------------
                newcommandUD@firstoftwo[2]{#1}%
                newcommandUD@secondoftwo[2]{#2}%
                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]{%
                romannumeral0expandafterUD@secondoftwostring{expandafter
                UD@secondoftwoexpandafter{expandafter{string#1}expandafter
                UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
                UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
                }%
                %%-----------------------------------------------------------------------------
                %% Check whether argument's first token is a catcode-1-character
                %%.............................................................................
                %% UD@CheckWhetherBrace{<Argument which is to be checked>}%
                %% {<Tokens to be delivered in case that argument
                %% which is to be checked has leading
                %% catcode-1-token>}%
                %% {<Tokens to be delivered in case that argument
                %% which is to be checked has no leading
                %% catcode-1-token>}%
                newcommandUD@CheckWhetherBrace[1]{%
                romannumeral0expandafterUD@secondoftwoexpandafter{expandafter{%
                string#1.}expandafterUD@firstoftwoexpandafter{expandafter
                UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                UD@firstoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                }%
                %%==============================================================================
                %% Check whether brace-balanced argument starts with a space-token
                %%..............................................................................
                %% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
                %% {<Tokens to be delivered in case <argument
                %% which is to be checked>'s 1st token is a
                %% space-token>}%
                %% {<Tokens to be delivered in case <argument
                %% which is to be checked>'s 1st token is not
                %% a space-token>}%
                newcommandUD@CheckWhetherLeadingSpace[1]{%
                romannumeral0UD@CheckWhetherNull{#1}%
                {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
                }%
                newcommandUD@CheckWhetherLeadingSpaceB{}%
                longdefUD@CheckWhetherLeadingSpaceB#1 {%
                expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
                {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
                {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                expandafterexpandafterexpandafter}expandafterexpandafter
                expandafter}expandafterUD@secondoftwoexpandafter{string}%
                }%
                %%-----------------------------------------------------------------------------
                %% Check whether argument does not contain "!":
                %%.............................................................................
                newcommandUD@GobbleToExclam{}%
                longdefUD@GobbleToExclam#1!{}%
                newcommandUD@CheckWhetherNoExclam[1]{%
                expandafterUD@CheckWhetherNullexpandafter{UD@GobbleToExclam#1!}%
                }%
                %%----------------------------------------------------------------------
                %% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
                %% {<Tokens to be delivered in case <argument
                %% which is to be checked>'s 1st token is
                %% UD@CollectMore>}%
                %% {<Tokens to be delivered in case <argument
                %% which is to be checked>'s 1st token is not
                %% UD@CollectMore>}%
                %%----------------------------------------------------------------------
                newcommandUD@CheckForMoreTransformations[1]{%
                romannumeral0UD@CheckWhetherBrace{#1}{%
                expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
                }{%
                UD@CheckWhetherLeadingSpace{#1}{%
                expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
                }{%
                UD@CheckWhetherNull{#1}{%
                expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
                }{%
                expandafterUD@secondoftwostring{UD@MoreTransformationsFork#1}{}%
                }%
                }%
                }%
                }%
                newcommandUD@MoreTransformationsFork[1]{%
                UD@CheckWhetherNoExclam{#1}{%
                UD@@MoreTransformationsFork!#1!V!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% U
                !U!#1!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% V
                !U!V!#1!x!y!z!{UD@Exchange{UD@firstoftwo}}% W
                !U!V!W!#1!y!z!{UD@Exchange{UD@firstoftwo}}% x
                !U!V!W!x!#1!z!{UD@Exchange{UD@firstoftwo}}% y
                !U!V!W!x!y!#1!{UD@Exchange{UD@firstoftwo}}% z
                !U!V!W!x!y!z!{UD@Exchange{UD@secondoftwo}}% something else without !
                !!!!%
                }{UD@Exchange{UD@secondoftwo}}% something else with !
                {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                expandafterexpandafterexpandafter}expandafterexpandafter
                expandafter}expandafterUD@secondoftwoexpandafter{string}%
                }%
                newcommandUD@@MoreTransformationsFork{}%
                longdefUD@@MoreTransformationsFork#1!U!V!W!x!y!z!#2#3!!!!{#2}%
                %%......................................................................
                newcommandUD@CollectMore{UD@CollectMore@B{}}%
                newcommandUD@CollectMore@B[3]{%
                UD@CheckForMoreTransformations{#2}{%
                expandafterexpandafterexpandafterUD@Exchange
                expandafterexpandafterexpandafter{%
                expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
                }{%
                ensuremath{{#2}^{(#3#1)}}%
                }%
                }%
                %%......................................................................

                newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
                newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
                newcommandz[2]{UD@CollectMore{#1}{z=#2}}%

                newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
                newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
                newcommandW[2]{UD@CollectMore{#1}{w=#2}}%

                makeatother

                begin{document}

                verb|x{F}{a}|: % yields F^{(x=a)}
                x{F}{a}% gives F^{(x=a)}

                verb|y{F}{b}|: % yields F^{(y=b)}
                y{F}{b}% gives F^{(y=b)}

                verb|z{F}{c}|: % yields F^{(z=b)}
                z{F}{c}% gives F^{(z=b)}

                verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
                x{y{F}{b}}{a}% gives F^{(y=b, x=a)}

                verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
                x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}

                verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
                U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}

                end{document}


                enter image description here






                share|improve this answer

























                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  documentclass{article}
                  makeatletter
                  %%----------------------------------------------------------------------
                  %% Paraphernalia
                  %%----------------------------------------------------------------------
                  newcommandUD@firstoftwo[2]{#1}%
                  newcommandUD@secondoftwo[2]{#2}%
                  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>
                  %%
                  %% (romannumeral expansion was introduced in order to overcome the
                  %% concerns and worries about improperly balanced
                  %% if..else..fi constructs.)
                  %%
                  newcommandUD@CheckWhetherNull[1]{%
                  romannumeral0expandafterUD@secondoftwostring{expandafter
                  UD@secondoftwoexpandafter{expandafter{string#1}expandafter
                  UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
                  UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                  UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
                  }%
                  %%----------------------------------------------------------------------
                  %% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is
                  %% UD@CollectMore>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is not
                  %% UD@CollectMore>}%
                  %%----------------------------------------------------------------------
                  newcommandUD@CheckWhetherLeadingUD@CollectMore[1]{%
                  romannumeral0UD@CheckWhetherNull{#1}%
                  {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                  {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingUD@CollectMoreB.#1UD@CollectMore}{}}%
                  }%
                  newcommandUD@CheckWhetherLeadingUD@CollectMoreB{}%
                  longdefUD@CheckWhetherLeadingUD@CollectMoreB#1UD@CollectMore{%
                  expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
                  {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
                  {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                  expandafterexpandafterexpandafter}expandafterexpandafter
                  expandafter}expandafterUD@secondoftwoexpandafter{string}%
                  }%
                  %%......................................................................
                  newcommandUD@CollectMore{UD@CollectMore@B{}}%
                  newcommandUD@CollectMore@B[3]{%
                  expandafterUD@CheckWhetherLeadingUD@CollectMoreexpandafter{#2}{%
                  expandafterexpandafterexpandafterUD@Exchange
                  expandafterexpandafterexpandafter{%
                  expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
                  }{%
                  ensuremath{{#2}^{(#3#1)}}%
                  }%
                  }%
                  %%......................................................................

                  newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
                  newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
                  newcommandz[2]{UD@CollectMore{#1}{z=#2}}%

                  newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
                  newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
                  newcommandW[2]{UD@CollectMore{#1}{w=#2}}%

                  makeatother

                  begin{document}

                  verb|x{F}{a}|: % yields F^{(x=a)}
                  x{F}{a}% gives F^{(x=a)}

                  verb|y{F}{b}|: % yields F^{(y=b)}
                  y{F}{b}% gives F^{(y=b)}

                  verb|z{F}{c}|: % yields F^{(z=b)}
                  z{F}{c}% gives F^{(z=b)}

                  verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
                  x{y{F}{b}}{a}% gives F^{(y=b, x=a)}

                  verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
                  x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}

                  verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
                  U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}

                  end{document}


                  enter image description here





                  With the example above, the routine for checking for another nested transformation does attempt top-level-expansion to the first token of a transformation-macro's first argument in any case.

                  In edge cases this might cause problems.



                  The example below includes a checking routine with some brace-hacks which does the check without attempting to top-level-expand the first token of a transformation-macro's first argument and which applies top-level-expansion to that token only in case it is one of the tokens that are used as transformation-macros.



                  Advantage:



                  This is more safe even in edge cases.



                  Disadvantages:



                  In case you wish to rename some of the transformation-macros or wish to add some transformation-macros, you need to adjust
                  the checking-mechanism (UD@MoreTransformationsFork, UD@@MoreTransformationsFork) as well as it does check on the presence of tokens and not on their meaning.



                  The load of code is a bit larger: When grabbing the first token of an argument for checking whether it is either x or y or z or the like, you also need to take into account that the very first token of the argument could as well be a space-token or a curly opening-brace or that the argument might be empty, and as you check on the presence of one of several tokens, you need code for cranking out several cases.



                  documentclass{article}
                  makeatletter
                  %%----------------------------------------------------------------------
                  %% Paraphernalia
                  %%----------------------------------------------------------------------
                  newcommandUD@firstoftwo[2]{#1}%
                  newcommandUD@secondoftwo[2]{#2}%
                  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]{%
                  romannumeral0expandafterUD@secondoftwostring{expandafter
                  UD@secondoftwoexpandafter{expandafter{string#1}expandafter
                  UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
                  UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                  UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
                  }%
                  %%-----------------------------------------------------------------------------
                  %% Check whether argument's first token is a catcode-1-character
                  %%.............................................................................
                  %% UD@CheckWhetherBrace{<Argument which is to be checked>}%
                  %% {<Tokens to be delivered in case that argument
                  %% which is to be checked has leading
                  %% catcode-1-token>}%
                  %% {<Tokens to be delivered in case that argument
                  %% which is to be checked has no leading
                  %% catcode-1-token>}%
                  newcommandUD@CheckWhetherBrace[1]{%
                  romannumeral0expandafterUD@secondoftwoexpandafter{expandafter{%
                  string#1.}expandafterUD@firstoftwoexpandafter{expandafter
                  UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                  UD@firstoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                  }%
                  %%==============================================================================
                  %% Check whether brace-balanced argument starts with a space-token
                  %%..............................................................................
                  %% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is a
                  %% space-token>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is not
                  %% a space-token>}%
                  newcommandUD@CheckWhetherLeadingSpace[1]{%
                  romannumeral0UD@CheckWhetherNull{#1}%
                  {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                  {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
                  }%
                  newcommandUD@CheckWhetherLeadingSpaceB{}%
                  longdefUD@CheckWhetherLeadingSpaceB#1 {%
                  expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
                  {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
                  {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                  expandafterexpandafterexpandafter}expandafterexpandafter
                  expandafter}expandafterUD@secondoftwoexpandafter{string}%
                  }%
                  %%-----------------------------------------------------------------------------
                  %% Check whether argument does not contain "!":
                  %%.............................................................................
                  newcommandUD@GobbleToExclam{}%
                  longdefUD@GobbleToExclam#1!{}%
                  newcommandUD@CheckWhetherNoExclam[1]{%
                  expandafterUD@CheckWhetherNullexpandafter{UD@GobbleToExclam#1!}%
                  }%
                  %%----------------------------------------------------------------------
                  %% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is
                  %% UD@CollectMore>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is not
                  %% UD@CollectMore>}%
                  %%----------------------------------------------------------------------
                  newcommandUD@CheckForMoreTransformations[1]{%
                  romannumeral0UD@CheckWhetherBrace{#1}{%
                  expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
                  }{%
                  UD@CheckWhetherLeadingSpace{#1}{%
                  expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
                  }{%
                  UD@CheckWhetherNull{#1}{%
                  expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
                  }{%
                  expandafterUD@secondoftwostring{UD@MoreTransformationsFork#1}{}%
                  }%
                  }%
                  }%
                  }%
                  newcommandUD@MoreTransformationsFork[1]{%
                  UD@CheckWhetherNoExclam{#1}{%
                  UD@@MoreTransformationsFork!#1!V!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% U
                  !U!#1!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% V
                  !U!V!#1!x!y!z!{UD@Exchange{UD@firstoftwo}}% W
                  !U!V!W!#1!y!z!{UD@Exchange{UD@firstoftwo}}% x
                  !U!V!W!x!#1!z!{UD@Exchange{UD@firstoftwo}}% y
                  !U!V!W!x!y!#1!{UD@Exchange{UD@firstoftwo}}% z
                  !U!V!W!x!y!z!{UD@Exchange{UD@secondoftwo}}% something else without !
                  !!!!%
                  }{UD@Exchange{UD@secondoftwo}}% something else with !
                  {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                  expandafterexpandafterexpandafter}expandafterexpandafter
                  expandafter}expandafterUD@secondoftwoexpandafter{string}%
                  }%
                  newcommandUD@@MoreTransformationsFork{}%
                  longdefUD@@MoreTransformationsFork#1!U!V!W!x!y!z!#2#3!!!!{#2}%
                  %%......................................................................
                  newcommandUD@CollectMore{UD@CollectMore@B{}}%
                  newcommandUD@CollectMore@B[3]{%
                  UD@CheckForMoreTransformations{#2}{%
                  expandafterexpandafterexpandafterUD@Exchange
                  expandafterexpandafterexpandafter{%
                  expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
                  }{%
                  ensuremath{{#2}^{(#3#1)}}%
                  }%
                  }%
                  %%......................................................................

                  newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
                  newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
                  newcommandz[2]{UD@CollectMore{#1}{z=#2}}%

                  newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
                  newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
                  newcommandW[2]{UD@CollectMore{#1}{w=#2}}%

                  makeatother

                  begin{document}

                  verb|x{F}{a}|: % yields F^{(x=a)}
                  x{F}{a}% gives F^{(x=a)}

                  verb|y{F}{b}|: % yields F^{(y=b)}
                  y{F}{b}% gives F^{(y=b)}

                  verb|z{F}{c}|: % yields F^{(z=b)}
                  z{F}{c}% gives F^{(z=b)}

                  verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
                  x{y{F}{b}}{a}% gives F^{(y=b, x=a)}

                  verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
                  x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}

                  verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
                  U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}

                  end{document}


                  enter image description here






                  share|improve this answer














                  documentclass{article}
                  makeatletter
                  %%----------------------------------------------------------------------
                  %% Paraphernalia
                  %%----------------------------------------------------------------------
                  newcommandUD@firstoftwo[2]{#1}%
                  newcommandUD@secondoftwo[2]{#2}%
                  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>
                  %%
                  %% (romannumeral expansion was introduced in order to overcome the
                  %% concerns and worries about improperly balanced
                  %% if..else..fi constructs.)
                  %%
                  newcommandUD@CheckWhetherNull[1]{%
                  romannumeral0expandafterUD@secondoftwostring{expandafter
                  UD@secondoftwoexpandafter{expandafter{string#1}expandafter
                  UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
                  UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                  UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
                  }%
                  %%----------------------------------------------------------------------
                  %% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is
                  %% UD@CollectMore>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is not
                  %% UD@CollectMore>}%
                  %%----------------------------------------------------------------------
                  newcommandUD@CheckWhetherLeadingUD@CollectMore[1]{%
                  romannumeral0UD@CheckWhetherNull{#1}%
                  {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                  {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingUD@CollectMoreB.#1UD@CollectMore}{}}%
                  }%
                  newcommandUD@CheckWhetherLeadingUD@CollectMoreB{}%
                  longdefUD@CheckWhetherLeadingUD@CollectMoreB#1UD@CollectMore{%
                  expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
                  {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
                  {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                  expandafterexpandafterexpandafter}expandafterexpandafter
                  expandafter}expandafterUD@secondoftwoexpandafter{string}%
                  }%
                  %%......................................................................
                  newcommandUD@CollectMore{UD@CollectMore@B{}}%
                  newcommandUD@CollectMore@B[3]{%
                  expandafterUD@CheckWhetherLeadingUD@CollectMoreexpandafter{#2}{%
                  expandafterexpandafterexpandafterUD@Exchange
                  expandafterexpandafterexpandafter{%
                  expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
                  }{%
                  ensuremath{{#2}^{(#3#1)}}%
                  }%
                  }%
                  %%......................................................................

                  newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
                  newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
                  newcommandz[2]{UD@CollectMore{#1}{z=#2}}%

                  newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
                  newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
                  newcommandW[2]{UD@CollectMore{#1}{w=#2}}%

                  makeatother

                  begin{document}

                  verb|x{F}{a}|: % yields F^{(x=a)}
                  x{F}{a}% gives F^{(x=a)}

                  verb|y{F}{b}|: % yields F^{(y=b)}
                  y{F}{b}% gives F^{(y=b)}

                  verb|z{F}{c}|: % yields F^{(z=b)}
                  z{F}{c}% gives F^{(z=b)}

                  verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
                  x{y{F}{b}}{a}% gives F^{(y=b, x=a)}

                  verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
                  x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}

                  verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
                  U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}

                  end{document}


                  enter image description here





                  With the example above, the routine for checking for another nested transformation does attempt top-level-expansion to the first token of a transformation-macro's first argument in any case.

                  In edge cases this might cause problems.



                  The example below includes a checking routine with some brace-hacks which does the check without attempting to top-level-expand the first token of a transformation-macro's first argument and which applies top-level-expansion to that token only in case it is one of the tokens that are used as transformation-macros.



                  Advantage:



                  This is more safe even in edge cases.



                  Disadvantages:



                  In case you wish to rename some of the transformation-macros or wish to add some transformation-macros, you need to adjust
                  the checking-mechanism (UD@MoreTransformationsFork, UD@@MoreTransformationsFork) as well as it does check on the presence of tokens and not on their meaning.



                  The load of code is a bit larger: When grabbing the first token of an argument for checking whether it is either x or y or z or the like, you also need to take into account that the very first token of the argument could as well be a space-token or a curly opening-brace or that the argument might be empty, and as you check on the presence of one of several tokens, you need code for cranking out several cases.



                  documentclass{article}
                  makeatletter
                  %%----------------------------------------------------------------------
                  %% Paraphernalia
                  %%----------------------------------------------------------------------
                  newcommandUD@firstoftwo[2]{#1}%
                  newcommandUD@secondoftwo[2]{#2}%
                  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]{%
                  romannumeral0expandafterUD@secondoftwostring{expandafter
                  UD@secondoftwoexpandafter{expandafter{string#1}expandafter
                  UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
                  UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                  UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
                  }%
                  %%-----------------------------------------------------------------------------
                  %% Check whether argument's first token is a catcode-1-character
                  %%.............................................................................
                  %% UD@CheckWhetherBrace{<Argument which is to be checked>}%
                  %% {<Tokens to be delivered in case that argument
                  %% which is to be checked has leading
                  %% catcode-1-token>}%
                  %% {<Tokens to be delivered in case that argument
                  %% which is to be checked has no leading
                  %% catcode-1-token>}%
                  newcommandUD@CheckWhetherBrace[1]{%
                  romannumeral0expandafterUD@secondoftwoexpandafter{expandafter{%
                  string#1.}expandafterUD@firstoftwoexpandafter{expandafter
                  UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                  UD@firstoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                  }%
                  %%==============================================================================
                  %% Check whether brace-balanced argument starts with a space-token
                  %%..............................................................................
                  %% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is a
                  %% space-token>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is not
                  %% a space-token>}%
                  newcommandUD@CheckWhetherLeadingSpace[1]{%
                  romannumeral0UD@CheckWhetherNull{#1}%
                  {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                  {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
                  }%
                  newcommandUD@CheckWhetherLeadingSpaceB{}%
                  longdefUD@CheckWhetherLeadingSpaceB#1 {%
                  expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
                  {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
                  {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                  expandafterexpandafterexpandafter}expandafterexpandafter
                  expandafter}expandafterUD@secondoftwoexpandafter{string}%
                  }%
                  %%-----------------------------------------------------------------------------
                  %% Check whether argument does not contain "!":
                  %%.............................................................................
                  newcommandUD@GobbleToExclam{}%
                  longdefUD@GobbleToExclam#1!{}%
                  newcommandUD@CheckWhetherNoExclam[1]{%
                  expandafterUD@CheckWhetherNullexpandafter{UD@GobbleToExclam#1!}%
                  }%
                  %%----------------------------------------------------------------------
                  %% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is
                  %% UD@CollectMore>}%
                  %% {<Tokens to be delivered in case <argument
                  %% which is to be checked>'s 1st token is not
                  %% UD@CollectMore>}%
                  %%----------------------------------------------------------------------
                  newcommandUD@CheckForMoreTransformations[1]{%
                  romannumeral0UD@CheckWhetherBrace{#1}{%
                  expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
                  }{%
                  UD@CheckWhetherLeadingSpace{#1}{%
                  expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
                  }{%
                  UD@CheckWhetherNull{#1}{%
                  expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
                  }{%
                  expandafterUD@secondoftwostring{UD@MoreTransformationsFork#1}{}%
                  }%
                  }%
                  }%
                  }%
                  newcommandUD@MoreTransformationsFork[1]{%
                  UD@CheckWhetherNoExclam{#1}{%
                  UD@@MoreTransformationsFork!#1!V!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% U
                  !U!#1!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% V
                  !U!V!#1!x!y!z!{UD@Exchange{UD@firstoftwo}}% W
                  !U!V!W!#1!y!z!{UD@Exchange{UD@firstoftwo}}% x
                  !U!V!W!x!#1!z!{UD@Exchange{UD@firstoftwo}}% y
                  !U!V!W!x!y!#1!{UD@Exchange{UD@firstoftwo}}% z
                  !U!V!W!x!y!z!{UD@Exchange{UD@secondoftwo}}% something else without !
                  !!!!%
                  }{UD@Exchange{UD@secondoftwo}}% something else with !
                  {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                  expandafterexpandafterexpandafter}expandafterexpandafter
                  expandafter}expandafterUD@secondoftwoexpandafter{string}%
                  }%
                  newcommandUD@@MoreTransformationsFork{}%
                  longdefUD@@MoreTransformationsFork#1!U!V!W!x!y!z!#2#3!!!!{#2}%
                  %%......................................................................
                  newcommandUD@CollectMore{UD@CollectMore@B{}}%
                  newcommandUD@CollectMore@B[3]{%
                  UD@CheckForMoreTransformations{#2}{%
                  expandafterexpandafterexpandafterUD@Exchange
                  expandafterexpandafterexpandafter{%
                  expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
                  }{%
                  ensuremath{{#2}^{(#3#1)}}%
                  }%
                  }%
                  %%......................................................................

                  newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
                  newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
                  newcommandz[2]{UD@CollectMore{#1}{z=#2}}%

                  newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
                  newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
                  newcommandW[2]{UD@CollectMore{#1}{w=#2}}%

                  makeatother

                  begin{document}

                  verb|x{F}{a}|: % yields F^{(x=a)}
                  x{F}{a}% gives F^{(x=a)}

                  verb|y{F}{b}|: % yields F^{(y=b)}
                  y{F}{b}% gives F^{(y=b)}

                  verb|z{F}{c}|: % yields F^{(z=b)}
                  z{F}{c}% gives F^{(z=b)}

                  verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
                  x{y{F}{b}}{a}% gives F^{(y=b, x=a)}

                  verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
                  x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}

                  verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
                  U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}

                  end{document}


                  enter image description here







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Dec 6 at 12:23

























                  answered Dec 4 at 23:37









                  Ulrich Diez

                  3,920615




                  3,920615






























                      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.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • 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%2f463149%2fchanging-the-effect-of-a-command-in-another%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 to change which sound is reproduced for terminal bell?

                      Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

                      Can I use Tabulator js library in my java Spring + Thymeleaf project?