Problems with def











up vote
7
down vote

favorite












I have created the following macros in LaTeX:



deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}


Where twomate is a 2x2 matrix, twoclmn creates a 2x1 column vector, and pwr is a command to raise the argument to the power.
However, if I try to do the following:



$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )$$


I get an error. However, if I replace the last entry with something that is not a def command:



$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),5 )$$


The document complies successfully. In addition, the following does not compile successfully:



$$twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t) + frac25 t epwr(2t))$$


But the following does:



$$twoclmn(frac{6}{25}e^{2t}-frac15te^{2t},-frac{2}{25}e^{2t} + frac25 t e^{2t})$$


So the problem seems to be the nested def commands. How may I nest def commands, without the compiler complaining?










share|improve this question







New contributor




Hossmeister is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • Since you're using LaTeX, please consider using [ ... ] instead of $$ ... $$, as the latter causes some inconsistencies.
    – AJFarmar
    11 hours ago















up vote
7
down vote

favorite












I have created the following macros in LaTeX:



deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}


Where twomate is a 2x2 matrix, twoclmn creates a 2x1 column vector, and pwr is a command to raise the argument to the power.
However, if I try to do the following:



$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )$$


I get an error. However, if I replace the last entry with something that is not a def command:



$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),5 )$$


The document complies successfully. In addition, the following does not compile successfully:



$$twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t) + frac25 t epwr(2t))$$


But the following does:



$$twoclmn(frac{6}{25}e^{2t}-frac15te^{2t},-frac{2}{25}e^{2t} + frac25 t e^{2t})$$


So the problem seems to be the nested def commands. How may I nest def commands, without the compiler complaining?










share|improve this question







New contributor




Hossmeister is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • Since you're using LaTeX, please consider using [ ... ] instead of $$ ... $$, as the latter causes some inconsistencies.
    – AJFarmar
    11 hours ago













up vote
7
down vote

favorite









up vote
7
down vote

favorite











I have created the following macros in LaTeX:



deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}


Where twomate is a 2x2 matrix, twoclmn creates a 2x1 column vector, and pwr is a command to raise the argument to the power.
However, if I try to do the following:



$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )$$


I get an error. However, if I replace the last entry with something that is not a def command:



$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),5 )$$


The document complies successfully. In addition, the following does not compile successfully:



$$twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t) + frac25 t epwr(2t))$$


But the following does:



$$twoclmn(frac{6}{25}e^{2t}-frac15te^{2t},-frac{2}{25}e^{2t} + frac25 t e^{2t})$$


So the problem seems to be the nested def commands. How may I nest def commands, without the compiler complaining?










share|improve this question







New contributor




Hossmeister is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











I have created the following macros in LaTeX:



deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}


Where twomate is a 2x2 matrix, twoclmn creates a 2x1 column vector, and pwr is a command to raise the argument to the power.
However, if I try to do the following:



$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )$$


I get an error. However, if I replace the last entry with something that is not a def command:



$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),5 )$$


The document complies successfully. In addition, the following does not compile successfully:



$$twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t) + frac25 t epwr(2t))$$


But the following does:



$$twoclmn(frac{6}{25}e^{2t}-frac15te^{2t},-frac{2}{25}e^{2t} + frac25 t e^{2t})$$


So the problem seems to be the nested def commands. How may I nest def commands, without the compiler complaining?







math-mode macros






share|improve this question







New contributor




Hossmeister is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question







New contributor




Hossmeister is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question






New contributor




Hossmeister is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked yesterday









Hossmeister

383




383




New contributor




Hossmeister is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Hossmeister is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Hossmeister is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • Since you're using LaTeX, please consider using [ ... ] instead of $$ ... $$, as the latter causes some inconsistencies.
    – AJFarmar
    11 hours ago


















  • Since you're using LaTeX, please consider using [ ... ] instead of $$ ... $$, as the latter causes some inconsistencies.
    – AJFarmar
    11 hours ago
















Since you're using LaTeX, please consider using [ ... ] instead of $$ ... $$, as the latter causes some inconsistencies.
– AJFarmar
11 hours ago




Since you're using LaTeX, please consider using [ ... ] instead of $$ ... $$, as the latter causes some inconsistencies.
– AJFarmar
11 hours ago










4 Answers
4






active

oldest

votes

















up vote
10
down vote



accepted










You can use xparse for this job, because the r argument type takes care of nesting.



documentclass{article}
usepackage{amsmath}
usepackage{xparse}

NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}r()}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1&#2\#3&#4end{pmatrix}%
}
NewDocumentCommand{pwr}{r()}{^{#1}}

begin{document}

[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )
]

end{document}


However, using () as delimiters doesn't seem a good idea. The following is as clear and behaves better with syntax coloring of front ends.



documentclass{article}
usepackage{amsmath}
usepackage{xparse}

NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}m}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1&#2\#3&#4end{pmatrix}%
}
NewDocumentCommand{pwr}{m}{^{#1}}

begin{document}

[
twomate{3epwr{-3t},epwr{2t},-epwr{-3t},-2epwr{2t}}
]

end{document}


enter image description here






share|improve this answer





















  • can one nest like this foo(a,bar(b,c,d),baz(e,f),g) ?
    – jfbu
    8 hours ago










  • @jfbu Yes, but why? There's no advantage whatsoever over braces.
    – egreg
    8 hours ago










  • ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
    – jfbu
    8 hours ago












  • actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
    – jfbu
    7 hours ago










  • @jfbu Without seeing how you define foo, bar and baz it's just guesswork.
    – egreg
    7 hours ago


















up vote
9
down vote













Your def contains a very specific sequence defined as the parameter text:



%           1   2   3   4   5
deftwomate(<1>,<2>,<3>,<4>){ ... }
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └ comma ┘ │
% └─── bracket ───┘


This parameter text is matched exactly in order (almost like a first-come-first-served style) to extract the four arguments <1>, <2>, <3> and <4>. Here's how the elements are grabbed for twomate with the above notation:



%       1           2         3           4          5
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └────── comma ────────┘ │
% └───────────────── bracket ──────────────────┘


It should be clear that the last bracket ) isn't properly captured for pwr. The way around it is to hide pwr(.) from twomate:



documentclass{article}

usepackage{amsmath}

deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
defpwr(#1){^{#1}}

begin{document}

[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),{-2epwr(2t)})
]

end{document}


This solves the problem only temporarily. If you nest elements, you'll run into similar problems because of the parameter text pattern matching. In general, it is safer to group arguments using {...}.






share|improve this answer






























    up vote
    5
    down vote













    TeX's delimited parameters parsing doesn't take nesting into account properly. So if you call twomate(3epwr(-3t), ...), the final ) for twomate isn't found at the end of that line but at the end of pwr(-3t). The improperly formed call of pwr then causes trouble.



    To hide nested calls of your commands, put them into { ... } groups (though this probably defeats the purpose):



    documentclass{article}
    usepackage{amsmath}

    deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
    defpwr(#1){^{#1}}
    deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}

    begin{document}
    [ twomate({3epwr(-3t)},{epwr(2t)},{-epwr(-3t)},{-2epwr(2t)}) ]
    end{document}


    enter image description here



    By the way, don't use $$ ... $$ for display math environments but LaTeX's or amsmath's variants like [ ... ].






    share|improve this answer






























      up vote
      2
      down vote













      original answer



      Here is a way to define macros fetching their arguments like "functions" in many programming language.



      It is lifted from the xintexpr code.



      I had a bit forgotten the details, and left the code comments of XINT_isbalanced_a for those interested.



      now that things come back more to my memory: of course comma separation of arguments will cause further issues. The xintexpr parser does not use at all this mechanism for implementing comma separated arguments of "functions". The mechanism as here is applied only for things such as seq(<expression>, x=1..10) where the <expression> if fetched as delimited by a comma, and then the balancing test is applied to it in case it was for example seq(myfunction(x,x^2),x=1..10) where the first comma would have been intially mistakendly taken as delimiter, but then the code realizes it is not balanced so it goes further.



      thus, now that I think about it, nesting here would need checking the arguments picked up by comma delimited macros are balanced with respect to parentheses. I have not applied it yet, as the poor man approach here is still very low-weight and is enough for the OP use cases



      See below how applyfunction is to be used.



      (but as I explained in paragraphs above this is not provided as a nestable thing, only "functions" with 1 argument can be nested inside others; perhaps I will edit later to provide fuller solution).



      Thus this is a no-package solution.



      documentclass{article}

      % copy over some utility code from package xintexpr
      catcode`_ 11

      makeatletter
      letxint_c_monem@ne
      letxint_c_z@
      letxint_c_i@ne
      longdefxint_bye #1xint_bye {}%
      makeatother
      % % end{macrocode}
      % subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
      % lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
      % it, to @ne if opening ( had no closing ) matching it, to z@ if expression
      % was balanced.|
      % begin{macrocode}
      % use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
      defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
      defXINT_isbalanced_b #1)#2%
      {xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
      % end{macrocode}
      % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
      % begin{macrocode}
      defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
      % end{macrocode}
      % lverb|#2 was xint_bye, was there a ) in original #1?|
      % begin{macrocode}
      defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
      {xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
      % end{macrocode}
      % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
      % begin{macrocode}
      defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
      % end{macrocode}
      % lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
      % we see a ). If we do, we then loop until no ( nor ) is to be found.|
      % begin{macrocode}
      defXINT_isbalanced_d #1)#2%
      {xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
      % end{macrocode}
      % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
      % begin{macrocode}
      defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%

      % Define a utility to apply a "function", comma separated arguments
      defapplyfunction #1(#2)%
      {%
      ifcaseXINT_isbalanced_a relax #1#2(xint_bye)xint_bye
      expandafterapplyfunction_doit
      orexpandafterapplyfunction_again
      elseexpandafterwe_are_doomed
      fi {#1#2}%
      }%
      defapplyfunction_doit #1{#1,}
      defapplyfunction_again #1{applyfunction {#1)}(}

      catcode`_ 8

      usepackage{amsmath}


      makeatletter

      % function wrappers
      deftwomate{applyfunctiontwomate@csv}
      defpwr{applyfunctionpwr@csv}
      deftwoclmn{applyfunctiontwoclmn@csv}

      % define macros with comma delimited arguments
      deftwomate@csv#1,#2,#3,#4,{begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
      defpwr@csv#1,{^{#1}}
      deftwoclmn@csv#1,#2,{begin{pmatrix}#1\#2end{pmatrix}}
      %

      makeatother

      begin{document}

      [
      twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
      ]
      [
      twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
      + frac25 t epwr(2t))
      ]
      end{document}


      enter image description here



      updated answer



      Original code allowed only nesting of "function" with one-argument inside other "functions".



      Updated code makes more general nesting possible, we will test it with this input



      foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))


      and it works.



      Notice that this code works only by expansion.



      Code:



      documentclass{article}
      usepackage{amsmath}

      % copy over some utility code from package xintexpr
      catcode`_ 11

      makeatletter
      letxint_c_monem@ne
      letxint_c_z@
      letxint_c_i@ne
      longdefxint_bye #1xint_bye {}%
      makeatother
      % NOTICE THAT ALL MACROS NEXT SHOULD BE MADE `long` ARGUABLY
      % IT WAS NOT NEEDED IN XINTEXPR CONTEXT
      % % end{macrocode}
      % subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
      % lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
      % it, to @ne if opening ( had no closing ) matching it, to z@ if expression
      % was balanced.|
      % begin{macrocode}
      % use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
      defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
      defXINT_isbalanced_b #1)#2%
      {xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
      % end{macrocode}
      % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
      % begin{macrocode}
      defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
      % end{macrocode}
      % lverb|#2 was xint_bye, was there a ) in original #1?|
      % begin{macrocode}
      defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
      {xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
      % end{macrocode}
      % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
      % begin{macrocode}
      defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
      % end{macrocode}
      % lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
      % we see a ). If we do, we then loop until no ( nor ) is to be found.|
      % begin{macrocode}
      defXINT_isbalanced_d #1)#2%
      {xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
      % end{macrocode}
      % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
      % begin{macrocode}
      defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%

      % New utility (expandable)
      longdefapplyfunction #1#2)%
      {%
      ifcaseXINT_isbalanced_a relax #1#2)(xint_bye)xint_bye
      expandafterapplyfunction_b
      orexpandafterapplyfunction_again
      elseexpandafterwe_are_doomed
      fi {#1#2}%
      }%
      longdefapplyfunction_again #1{applyfunction {#1)}}%
      longdefmy_bbye #1my_bbye {}%
      longdefapplyfunction_b #1{applyfunction_c #1,my_bbye,}%
      longdefapplyfunction_c #1({applyfunction_d #1{}{}}%
      % we will take care of brace removal another day
      longdefapplyfunction_d #1#2#3#4,%
      {%
      ifcaseXINT_isbalanced_a relax #3#4(xint_bye)xint_bye
      expandafterapplyfunction_e
      orexpandafterapplyfunction_d_again
      elseexpandafterwe_are_doomed
      fi #1{#2}{#3}{#4}%
      }%
      longdefapplyfunction_d_again #1#2#3#4%
      {%
      applyfunction_d #1{#2}{#3#4,}%
      }%
      longdefapplyfunction_e #1#2#3#4%
      {%
      my_bbye#4applyfunction_finishmy_bbye
      applyfunction_g #1{#2}{#3#4}%
      }%
      longdefapplyfunction_g #1#2#3{applyfunction_d #1{#2{#3}}{}}%
      longdefapplyfunction_finishmy_bbyeapplyfunction_g #1#2#3{#1#2}%

      catcode`_ 8

      %% USAGE
      % "functions" to be used as foo(a,b,c,...)
      % Syntax: applyfunctionnondelimitedmacro
      % Number of arguments is determined dynamically (at most 9)
      makeatletter
      newcommandtwomate{applyfunctiontwomate@macro}
      newcommandpwr{applyfunctionpwr@macro}
      newcommandtwoclmn{applyfunctiontwoclmn@macro}
      % define here the **non-delimited** auxiliary macros
      newcommandtwomate@macro[4]{begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
      newcommandpwr@macro[1]{^{#1}}
      newcommandtwoclmn@macro[2]{begin{pmatrix}#1\#2end{pmatrix}}
      makeatother


      %% TESTING NESTING
      makeatletter
      newcommandfoo{applyfunctionfoo@macro}
      newcommandfoo@macro[4]{left[#1+#2+#3+#4right]}
      letBarrelax
      newcommandBar{applyfunctionBar@macro}
      newcommandBar@macro[3]{left(#1*#2*#3right)}
      makeatother

      delimiterfactor1001

      begin{document}

      [
      twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
      ]
      [
      twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
      + frac25 t epwr(2t))
      ]
      [foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))]
      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
        });


        }
        });






        Hossmeister is a new contributor. Be nice, and check out our Code of Conduct.










         

        draft saved


        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f459229%2fproblems-with-def%23new-answer', 'question_page');
        }
        );

        Post as a guest
































        4 Answers
        4






        active

        oldest

        votes








        4 Answers
        4






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes








        up vote
        10
        down vote



        accepted










        You can use xparse for this job, because the r argument type takes care of nesting.



        documentclass{article}
        usepackage{amsmath}
        usepackage{xparse}

        NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}r()}{%
        maketwomate#1%
        }
        NewDocumentCommand{maketwomate}{mmmm}{%
        begin{pmatrix}#1&#2\#3&#4end{pmatrix}%
        }
        NewDocumentCommand{pwr}{r()}{^{#1}}

        begin{document}

        [
        twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )
        ]

        end{document}


        However, using () as delimiters doesn't seem a good idea. The following is as clear and behaves better with syntax coloring of front ends.



        documentclass{article}
        usepackage{amsmath}
        usepackage{xparse}

        NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}m}{%
        maketwomate#1%
        }
        NewDocumentCommand{maketwomate}{mmmm}{%
        begin{pmatrix}#1&#2\#3&#4end{pmatrix}%
        }
        NewDocumentCommand{pwr}{m}{^{#1}}

        begin{document}

        [
        twomate{3epwr{-3t},epwr{2t},-epwr{-3t},-2epwr{2t}}
        ]

        end{document}


        enter image description here






        share|improve this answer





















        • can one nest like this foo(a,bar(b,c,d),baz(e,f),g) ?
          – jfbu
          8 hours ago










        • @jfbu Yes, but why? There's no advantage whatsoever over braces.
          – egreg
          8 hours ago










        • ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
          – jfbu
          8 hours ago












        • actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
          – jfbu
          7 hours ago










        • @jfbu Without seeing how you define foo, bar and baz it's just guesswork.
          – egreg
          7 hours ago















        up vote
        10
        down vote



        accepted










        You can use xparse for this job, because the r argument type takes care of nesting.



        documentclass{article}
        usepackage{amsmath}
        usepackage{xparse}

        NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}r()}{%
        maketwomate#1%
        }
        NewDocumentCommand{maketwomate}{mmmm}{%
        begin{pmatrix}#1&#2\#3&#4end{pmatrix}%
        }
        NewDocumentCommand{pwr}{r()}{^{#1}}

        begin{document}

        [
        twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )
        ]

        end{document}


        However, using () as delimiters doesn't seem a good idea. The following is as clear and behaves better with syntax coloring of front ends.



        documentclass{article}
        usepackage{amsmath}
        usepackage{xparse}

        NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}m}{%
        maketwomate#1%
        }
        NewDocumentCommand{maketwomate}{mmmm}{%
        begin{pmatrix}#1&#2\#3&#4end{pmatrix}%
        }
        NewDocumentCommand{pwr}{m}{^{#1}}

        begin{document}

        [
        twomate{3epwr{-3t},epwr{2t},-epwr{-3t},-2epwr{2t}}
        ]

        end{document}


        enter image description here






        share|improve this answer





















        • can one nest like this foo(a,bar(b,c,d),baz(e,f),g) ?
          – jfbu
          8 hours ago










        • @jfbu Yes, but why? There's no advantage whatsoever over braces.
          – egreg
          8 hours ago










        • ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
          – jfbu
          8 hours ago












        • actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
          – jfbu
          7 hours ago










        • @jfbu Without seeing how you define foo, bar and baz it's just guesswork.
          – egreg
          7 hours ago













        up vote
        10
        down vote



        accepted







        up vote
        10
        down vote



        accepted






        You can use xparse for this job, because the r argument type takes care of nesting.



        documentclass{article}
        usepackage{amsmath}
        usepackage{xparse}

        NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}r()}{%
        maketwomate#1%
        }
        NewDocumentCommand{maketwomate}{mmmm}{%
        begin{pmatrix}#1&#2\#3&#4end{pmatrix}%
        }
        NewDocumentCommand{pwr}{r()}{^{#1}}

        begin{document}

        [
        twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )
        ]

        end{document}


        However, using () as delimiters doesn't seem a good idea. The following is as clear and behaves better with syntax coloring of front ends.



        documentclass{article}
        usepackage{amsmath}
        usepackage{xparse}

        NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}m}{%
        maketwomate#1%
        }
        NewDocumentCommand{maketwomate}{mmmm}{%
        begin{pmatrix}#1&#2\#3&#4end{pmatrix}%
        }
        NewDocumentCommand{pwr}{m}{^{#1}}

        begin{document}

        [
        twomate{3epwr{-3t},epwr{2t},-epwr{-3t},-2epwr{2t}}
        ]

        end{document}


        enter image description here






        share|improve this answer












        You can use xparse for this job, because the r argument type takes care of nesting.



        documentclass{article}
        usepackage{amsmath}
        usepackage{xparse}

        NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}r()}{%
        maketwomate#1%
        }
        NewDocumentCommand{maketwomate}{mmmm}{%
        begin{pmatrix}#1&#2\#3&#4end{pmatrix}%
        }
        NewDocumentCommand{pwr}{r()}{^{#1}}

        begin{document}

        [
        twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )
        ]

        end{document}


        However, using () as delimiters doesn't seem a good idea. The following is as clear and behaves better with syntax coloring of front ends.



        documentclass{article}
        usepackage{amsmath}
        usepackage{xparse}

        NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}m}{%
        maketwomate#1%
        }
        NewDocumentCommand{maketwomate}{mmmm}{%
        begin{pmatrix}#1&#2\#3&#4end{pmatrix}%
        }
        NewDocumentCommand{pwr}{m}{^{#1}}

        begin{document}

        [
        twomate{3epwr{-3t},epwr{2t},-epwr{-3t},-2epwr{2t}}
        ]

        end{document}


        enter image description here







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered yesterday









        egreg

        696k8518483108




        696k8518483108












        • can one nest like this foo(a,bar(b,c,d),baz(e,f),g) ?
          – jfbu
          8 hours ago










        • @jfbu Yes, but why? There's no advantage whatsoever over braces.
          – egreg
          8 hours ago










        • ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
          – jfbu
          8 hours ago












        • actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
          – jfbu
          7 hours ago










        • @jfbu Without seeing how you define foo, bar and baz it's just guesswork.
          – egreg
          7 hours ago


















        • can one nest like this foo(a,bar(b,c,d),baz(e,f),g) ?
          – jfbu
          8 hours ago










        • @jfbu Yes, but why? There's no advantage whatsoever over braces.
          – egreg
          8 hours ago










        • ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
          – jfbu
          8 hours ago












        • actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
          – jfbu
          7 hours ago










        • @jfbu Without seeing how you define foo, bar and baz it's just guesswork.
          – egreg
          7 hours ago
















        can one nest like this foo(a,bar(b,c,d),baz(e,f),g) ?
        – jfbu
        8 hours ago




        can one nest like this foo(a,bar(b,c,d),baz(e,f),g) ?
        – jfbu
        8 hours ago












        @jfbu Yes, but why? There's no advantage whatsoever over braces.
        – egreg
        8 hours ago




        @jfbu Yes, but why? There's no advantage whatsoever over braces.
        – egreg
        8 hours ago












        ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
        – jfbu
        8 hours ago






        ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
        – jfbu
        8 hours ago














        actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
        – jfbu
        7 hours ago




        actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
        – jfbu
        7 hours ago












        @jfbu Without seeing how you define foo, bar and baz it's just guesswork.
        – egreg
        7 hours ago




        @jfbu Without seeing how you define foo, bar and baz it's just guesswork.
        – egreg
        7 hours ago










        up vote
        9
        down vote













        Your def contains a very specific sequence defined as the parameter text:



        %           1   2   3   4   5
        deftwomate(<1>,<2>,<3>,<4>){ ... }
        % ^ ^ ^ ^ ^
        % │ │ │ │ │
        % │ └ comma ┘ │
        % └─── bracket ───┘


        This parameter text is matched exactly in order (almost like a first-come-first-served style) to extract the four arguments <1>, <2>, <3> and <4>. Here's how the elements are grabbed for twomate with the above notation:



        %       1           2         3           4          5
        twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
        % ^ ^ ^ ^ ^
        % │ │ │ │ │
        % │ └────── comma ────────┘ │
        % └───────────────── bracket ──────────────────┘


        It should be clear that the last bracket ) isn't properly captured for pwr. The way around it is to hide pwr(.) from twomate:



        documentclass{article}

        usepackage{amsmath}

        deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
        defpwr(#1){^{#1}}

        begin{document}

        [
        twomate(3epwr(-3t),epwr(2t),-epwr(-3t),{-2epwr(2t)})
        ]

        end{document}


        This solves the problem only temporarily. If you nest elements, you'll run into similar problems because of the parameter text pattern matching. In general, it is safer to group arguments using {...}.






        share|improve this answer



























          up vote
          9
          down vote













          Your def contains a very specific sequence defined as the parameter text:



          %           1   2   3   4   5
          deftwomate(<1>,<2>,<3>,<4>){ ... }
          % ^ ^ ^ ^ ^
          % │ │ │ │ │
          % │ └ comma ┘ │
          % └─── bracket ───┘


          This parameter text is matched exactly in order (almost like a first-come-first-served style) to extract the four arguments <1>, <2>, <3> and <4>. Here's how the elements are grabbed for twomate with the above notation:



          %       1           2         3           4          5
          twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
          % ^ ^ ^ ^ ^
          % │ │ │ │ │
          % │ └────── comma ────────┘ │
          % └───────────────── bracket ──────────────────┘


          It should be clear that the last bracket ) isn't properly captured for pwr. The way around it is to hide pwr(.) from twomate:



          documentclass{article}

          usepackage{amsmath}

          deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
          defpwr(#1){^{#1}}

          begin{document}

          [
          twomate(3epwr(-3t),epwr(2t),-epwr(-3t),{-2epwr(2t)})
          ]

          end{document}


          This solves the problem only temporarily. If you nest elements, you'll run into similar problems because of the parameter text pattern matching. In general, it is safer to group arguments using {...}.






          share|improve this answer

























            up vote
            9
            down vote










            up vote
            9
            down vote









            Your def contains a very specific sequence defined as the parameter text:



            %           1   2   3   4   5
            deftwomate(<1>,<2>,<3>,<4>){ ... }
            % ^ ^ ^ ^ ^
            % │ │ │ │ │
            % │ └ comma ┘ │
            % └─── bracket ───┘


            This parameter text is matched exactly in order (almost like a first-come-first-served style) to extract the four arguments <1>, <2>, <3> and <4>. Here's how the elements are grabbed for twomate with the above notation:



            %       1           2         3           4          5
            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
            % ^ ^ ^ ^ ^
            % │ │ │ │ │
            % │ └────── comma ────────┘ │
            % └───────────────── bracket ──────────────────┘


            It should be clear that the last bracket ) isn't properly captured for pwr. The way around it is to hide pwr(.) from twomate:



            documentclass{article}

            usepackage{amsmath}

            deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
            defpwr(#1){^{#1}}

            begin{document}

            [
            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),{-2epwr(2t)})
            ]

            end{document}


            This solves the problem only temporarily. If you nest elements, you'll run into similar problems because of the parameter text pattern matching. In general, it is safer to group arguments using {...}.






            share|improve this answer














            Your def contains a very specific sequence defined as the parameter text:



            %           1   2   3   4   5
            deftwomate(<1>,<2>,<3>,<4>){ ... }
            % ^ ^ ^ ^ ^
            % │ │ │ │ │
            % │ └ comma ┘ │
            % └─── bracket ───┘


            This parameter text is matched exactly in order (almost like a first-come-first-served style) to extract the four arguments <1>, <2>, <3> and <4>. Here's how the elements are grabbed for twomate with the above notation:



            %       1           2         3           4          5
            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
            % ^ ^ ^ ^ ^
            % │ │ │ │ │
            % │ └────── comma ────────┘ │
            % └───────────────── bracket ──────────────────┘


            It should be clear that the last bracket ) isn't properly captured for pwr. The way around it is to hide pwr(.) from twomate:



            documentclass{article}

            usepackage{amsmath}

            deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
            defpwr(#1){^{#1}}

            begin{document}

            [
            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),{-2epwr(2t)})
            ]

            end{document}


            This solves the problem only temporarily. If you nest elements, you'll run into similar problems because of the parameter text pattern matching. In general, it is safer to group arguments using {...}.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited yesterday

























            answered yesterday









            Werner

            429k589421618




            429k589421618






















                up vote
                5
                down vote













                TeX's delimited parameters parsing doesn't take nesting into account properly. So if you call twomate(3epwr(-3t), ...), the final ) for twomate isn't found at the end of that line but at the end of pwr(-3t). The improperly formed call of pwr then causes trouble.



                To hide nested calls of your commands, put them into { ... } groups (though this probably defeats the purpose):



                documentclass{article}
                usepackage{amsmath}

                deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                defpwr(#1){^{#1}}
                deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}

                begin{document}
                [ twomate({3epwr(-3t)},{epwr(2t)},{-epwr(-3t)},{-2epwr(2t)}) ]
                end{document}


                enter image description here



                By the way, don't use $$ ... $$ for display math environments but LaTeX's or amsmath's variants like [ ... ].






                share|improve this answer



























                  up vote
                  5
                  down vote













                  TeX's delimited parameters parsing doesn't take nesting into account properly. So if you call twomate(3epwr(-3t), ...), the final ) for twomate isn't found at the end of that line but at the end of pwr(-3t). The improperly formed call of pwr then causes trouble.



                  To hide nested calls of your commands, put them into { ... } groups (though this probably defeats the purpose):



                  documentclass{article}
                  usepackage{amsmath}

                  deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                  defpwr(#1){^{#1}}
                  deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}

                  begin{document}
                  [ twomate({3epwr(-3t)},{epwr(2t)},{-epwr(-3t)},{-2epwr(2t)}) ]
                  end{document}


                  enter image description here



                  By the way, don't use $$ ... $$ for display math environments but LaTeX's or amsmath's variants like [ ... ].






                  share|improve this answer

























                    up vote
                    5
                    down vote










                    up vote
                    5
                    down vote









                    TeX's delimited parameters parsing doesn't take nesting into account properly. So if you call twomate(3epwr(-3t), ...), the final ) for twomate isn't found at the end of that line but at the end of pwr(-3t). The improperly formed call of pwr then causes trouble.



                    To hide nested calls of your commands, put them into { ... } groups (though this probably defeats the purpose):



                    documentclass{article}
                    usepackage{amsmath}

                    deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                    defpwr(#1){^{#1}}
                    deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}

                    begin{document}
                    [ twomate({3epwr(-3t)},{epwr(2t)},{-epwr(-3t)},{-2epwr(2t)}) ]
                    end{document}


                    enter image description here



                    By the way, don't use $$ ... $$ for display math environments but LaTeX's or amsmath's variants like [ ... ].






                    share|improve this answer














                    TeX's delimited parameters parsing doesn't take nesting into account properly. So if you call twomate(3epwr(-3t), ...), the final ) for twomate isn't found at the end of that line but at the end of pwr(-3t). The improperly formed call of pwr then causes trouble.



                    To hide nested calls of your commands, put them into { ... } groups (though this probably defeats the purpose):



                    documentclass{article}
                    usepackage{amsmath}

                    deftwomate(#1,#2,#3,#4){begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                    defpwr(#1){^{#1}}
                    deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}

                    begin{document}
                    [ twomate({3epwr(-3t)},{epwr(2t)},{-epwr(-3t)},{-2epwr(2t)}) ]
                    end{document}


                    enter image description here



                    By the way, don't use $$ ... $$ for display math environments but LaTeX's or amsmath's variants like [ ... ].







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited yesterday

























                    answered yesterday









                    siracusa

                    4,31911127




                    4,31911127






















                        up vote
                        2
                        down vote













                        original answer



                        Here is a way to define macros fetching their arguments like "functions" in many programming language.



                        It is lifted from the xintexpr code.



                        I had a bit forgotten the details, and left the code comments of XINT_isbalanced_a for those interested.



                        now that things come back more to my memory: of course comma separation of arguments will cause further issues. The xintexpr parser does not use at all this mechanism for implementing comma separated arguments of "functions". The mechanism as here is applied only for things such as seq(<expression>, x=1..10) where the <expression> if fetched as delimited by a comma, and then the balancing test is applied to it in case it was for example seq(myfunction(x,x^2),x=1..10) where the first comma would have been intially mistakendly taken as delimiter, but then the code realizes it is not balanced so it goes further.



                        thus, now that I think about it, nesting here would need checking the arguments picked up by comma delimited macros are balanced with respect to parentheses. I have not applied it yet, as the poor man approach here is still very low-weight and is enough for the OP use cases



                        See below how applyfunction is to be used.



                        (but as I explained in paragraphs above this is not provided as a nestable thing, only "functions" with 1 argument can be nested inside others; perhaps I will edit later to provide fuller solution).



                        Thus this is a no-package solution.



                        documentclass{article}

                        % copy over some utility code from package xintexpr
                        catcode`_ 11

                        makeatletter
                        letxint_c_monem@ne
                        letxint_c_z@
                        letxint_c_i@ne
                        longdefxint_bye #1xint_bye {}%
                        makeatother
                        % % end{macrocode}
                        % subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
                        % lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
                        % it, to @ne if opening ( had no closing ) matching it, to z@ if expression
                        % was balanced.|
                        % begin{macrocode}
                        % use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
                        defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
                        defXINT_isbalanced_b #1)#2%
                        {xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
                        % end{macrocode}
                        % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                        % begin{macrocode}
                        defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
                        % end{macrocode}
                        % lverb|#2 was xint_bye, was there a ) in original #1?|
                        % begin{macrocode}
                        defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                        {xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
                        % end{macrocode}
                        % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                        % begin{macrocode}
                        defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
                        % end{macrocode}
                        % lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
                        % we see a ). If we do, we then loop until no ( nor ) is to be found.|
                        % begin{macrocode}
                        defXINT_isbalanced_d #1)#2%
                        {xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
                        % end{macrocode}
                        % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                        % begin{macrocode}
                        defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%

                        % Define a utility to apply a "function", comma separated arguments
                        defapplyfunction #1(#2)%
                        {%
                        ifcaseXINT_isbalanced_a relax #1#2(xint_bye)xint_bye
                        expandafterapplyfunction_doit
                        orexpandafterapplyfunction_again
                        elseexpandafterwe_are_doomed
                        fi {#1#2}%
                        }%
                        defapplyfunction_doit #1{#1,}
                        defapplyfunction_again #1{applyfunction {#1)}(}

                        catcode`_ 8

                        usepackage{amsmath}


                        makeatletter

                        % function wrappers
                        deftwomate{applyfunctiontwomate@csv}
                        defpwr{applyfunctionpwr@csv}
                        deftwoclmn{applyfunctiontwoclmn@csv}

                        % define macros with comma delimited arguments
                        deftwomate@csv#1,#2,#3,#4,{begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                        defpwr@csv#1,{^{#1}}
                        deftwoclmn@csv#1,#2,{begin{pmatrix}#1\#2end{pmatrix}}
                        %

                        makeatother

                        begin{document}

                        [
                        twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                        ]
                        [
                        twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
                        + frac25 t epwr(2t))
                        ]
                        end{document}


                        enter image description here



                        updated answer



                        Original code allowed only nesting of "function" with one-argument inside other "functions".



                        Updated code makes more general nesting possible, we will test it with this input



                        foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))


                        and it works.



                        Notice that this code works only by expansion.



                        Code:



                        documentclass{article}
                        usepackage{amsmath}

                        % copy over some utility code from package xintexpr
                        catcode`_ 11

                        makeatletter
                        letxint_c_monem@ne
                        letxint_c_z@
                        letxint_c_i@ne
                        longdefxint_bye #1xint_bye {}%
                        makeatother
                        % NOTICE THAT ALL MACROS NEXT SHOULD BE MADE `long` ARGUABLY
                        % IT WAS NOT NEEDED IN XINTEXPR CONTEXT
                        % % end{macrocode}
                        % subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
                        % lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
                        % it, to @ne if opening ( had no closing ) matching it, to z@ if expression
                        % was balanced.|
                        % begin{macrocode}
                        % use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
                        defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
                        defXINT_isbalanced_b #1)#2%
                        {xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
                        % end{macrocode}
                        % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                        % begin{macrocode}
                        defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
                        % end{macrocode}
                        % lverb|#2 was xint_bye, was there a ) in original #1?|
                        % begin{macrocode}
                        defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                        {xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
                        % end{macrocode}
                        % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                        % begin{macrocode}
                        defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
                        % end{macrocode}
                        % lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
                        % we see a ). If we do, we then loop until no ( nor ) is to be found.|
                        % begin{macrocode}
                        defXINT_isbalanced_d #1)#2%
                        {xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
                        % end{macrocode}
                        % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                        % begin{macrocode}
                        defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%

                        % New utility (expandable)
                        longdefapplyfunction #1#2)%
                        {%
                        ifcaseXINT_isbalanced_a relax #1#2)(xint_bye)xint_bye
                        expandafterapplyfunction_b
                        orexpandafterapplyfunction_again
                        elseexpandafterwe_are_doomed
                        fi {#1#2}%
                        }%
                        longdefapplyfunction_again #1{applyfunction {#1)}}%
                        longdefmy_bbye #1my_bbye {}%
                        longdefapplyfunction_b #1{applyfunction_c #1,my_bbye,}%
                        longdefapplyfunction_c #1({applyfunction_d #1{}{}}%
                        % we will take care of brace removal another day
                        longdefapplyfunction_d #1#2#3#4,%
                        {%
                        ifcaseXINT_isbalanced_a relax #3#4(xint_bye)xint_bye
                        expandafterapplyfunction_e
                        orexpandafterapplyfunction_d_again
                        elseexpandafterwe_are_doomed
                        fi #1{#2}{#3}{#4}%
                        }%
                        longdefapplyfunction_d_again #1#2#3#4%
                        {%
                        applyfunction_d #1{#2}{#3#4,}%
                        }%
                        longdefapplyfunction_e #1#2#3#4%
                        {%
                        my_bbye#4applyfunction_finishmy_bbye
                        applyfunction_g #1{#2}{#3#4}%
                        }%
                        longdefapplyfunction_g #1#2#3{applyfunction_d #1{#2{#3}}{}}%
                        longdefapplyfunction_finishmy_bbyeapplyfunction_g #1#2#3{#1#2}%

                        catcode`_ 8

                        %% USAGE
                        % "functions" to be used as foo(a,b,c,...)
                        % Syntax: applyfunctionnondelimitedmacro
                        % Number of arguments is determined dynamically (at most 9)
                        makeatletter
                        newcommandtwomate{applyfunctiontwomate@macro}
                        newcommandpwr{applyfunctionpwr@macro}
                        newcommandtwoclmn{applyfunctiontwoclmn@macro}
                        % define here the **non-delimited** auxiliary macros
                        newcommandtwomate@macro[4]{begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                        newcommandpwr@macro[1]{^{#1}}
                        newcommandtwoclmn@macro[2]{begin{pmatrix}#1\#2end{pmatrix}}
                        makeatother


                        %% TESTING NESTING
                        makeatletter
                        newcommandfoo{applyfunctionfoo@macro}
                        newcommandfoo@macro[4]{left[#1+#2+#3+#4right]}
                        letBarrelax
                        newcommandBar{applyfunctionBar@macro}
                        newcommandBar@macro[3]{left(#1*#2*#3right)}
                        makeatother

                        delimiterfactor1001

                        begin{document}

                        [
                        twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                        ]
                        [
                        twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
                        + frac25 t epwr(2t))
                        ]
                        [foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))]
                        end{document}


                        enter image description here






                        share|improve this answer



























                          up vote
                          2
                          down vote













                          original answer



                          Here is a way to define macros fetching their arguments like "functions" in many programming language.



                          It is lifted from the xintexpr code.



                          I had a bit forgotten the details, and left the code comments of XINT_isbalanced_a for those interested.



                          now that things come back more to my memory: of course comma separation of arguments will cause further issues. The xintexpr parser does not use at all this mechanism for implementing comma separated arguments of "functions". The mechanism as here is applied only for things such as seq(<expression>, x=1..10) where the <expression> if fetched as delimited by a comma, and then the balancing test is applied to it in case it was for example seq(myfunction(x,x^2),x=1..10) where the first comma would have been intially mistakendly taken as delimiter, but then the code realizes it is not balanced so it goes further.



                          thus, now that I think about it, nesting here would need checking the arguments picked up by comma delimited macros are balanced with respect to parentheses. I have not applied it yet, as the poor man approach here is still very low-weight and is enough for the OP use cases



                          See below how applyfunction is to be used.



                          (but as I explained in paragraphs above this is not provided as a nestable thing, only "functions" with 1 argument can be nested inside others; perhaps I will edit later to provide fuller solution).



                          Thus this is a no-package solution.



                          documentclass{article}

                          % copy over some utility code from package xintexpr
                          catcode`_ 11

                          makeatletter
                          letxint_c_monem@ne
                          letxint_c_z@
                          letxint_c_i@ne
                          longdefxint_bye #1xint_bye {}%
                          makeatother
                          % % end{macrocode}
                          % subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
                          % lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
                          % it, to @ne if opening ( had no closing ) matching it, to z@ if expression
                          % was balanced.|
                          % begin{macrocode}
                          % use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
                          defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
                          defXINT_isbalanced_b #1)#2%
                          {xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
                          % end{macrocode}
                          % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                          % begin{macrocode}
                          defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
                          % end{macrocode}
                          % lverb|#2 was xint_bye, was there a ) in original #1?|
                          % begin{macrocode}
                          defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                          {xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
                          % end{macrocode}
                          % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                          % begin{macrocode}
                          defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
                          % end{macrocode}
                          % lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
                          % we see a ). If we do, we then loop until no ( nor ) is to be found.|
                          % begin{macrocode}
                          defXINT_isbalanced_d #1)#2%
                          {xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
                          % end{macrocode}
                          % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                          % begin{macrocode}
                          defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%

                          % Define a utility to apply a "function", comma separated arguments
                          defapplyfunction #1(#2)%
                          {%
                          ifcaseXINT_isbalanced_a relax #1#2(xint_bye)xint_bye
                          expandafterapplyfunction_doit
                          orexpandafterapplyfunction_again
                          elseexpandafterwe_are_doomed
                          fi {#1#2}%
                          }%
                          defapplyfunction_doit #1{#1,}
                          defapplyfunction_again #1{applyfunction {#1)}(}

                          catcode`_ 8

                          usepackage{amsmath}


                          makeatletter

                          % function wrappers
                          deftwomate{applyfunctiontwomate@csv}
                          defpwr{applyfunctionpwr@csv}
                          deftwoclmn{applyfunctiontwoclmn@csv}

                          % define macros with comma delimited arguments
                          deftwomate@csv#1,#2,#3,#4,{begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                          defpwr@csv#1,{^{#1}}
                          deftwoclmn@csv#1,#2,{begin{pmatrix}#1\#2end{pmatrix}}
                          %

                          makeatother

                          begin{document}

                          [
                          twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                          ]
                          [
                          twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
                          + frac25 t epwr(2t))
                          ]
                          end{document}


                          enter image description here



                          updated answer



                          Original code allowed only nesting of "function" with one-argument inside other "functions".



                          Updated code makes more general nesting possible, we will test it with this input



                          foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))


                          and it works.



                          Notice that this code works only by expansion.



                          Code:



                          documentclass{article}
                          usepackage{amsmath}

                          % copy over some utility code from package xintexpr
                          catcode`_ 11

                          makeatletter
                          letxint_c_monem@ne
                          letxint_c_z@
                          letxint_c_i@ne
                          longdefxint_bye #1xint_bye {}%
                          makeatother
                          % NOTICE THAT ALL MACROS NEXT SHOULD BE MADE `long` ARGUABLY
                          % IT WAS NOT NEEDED IN XINTEXPR CONTEXT
                          % % end{macrocode}
                          % subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
                          % lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
                          % it, to @ne if opening ( had no closing ) matching it, to z@ if expression
                          % was balanced.|
                          % begin{macrocode}
                          % use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
                          defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
                          defXINT_isbalanced_b #1)#2%
                          {xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
                          % end{macrocode}
                          % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                          % begin{macrocode}
                          defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
                          % end{macrocode}
                          % lverb|#2 was xint_bye, was there a ) in original #1?|
                          % begin{macrocode}
                          defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                          {xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
                          % end{macrocode}
                          % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                          % begin{macrocode}
                          defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
                          % end{macrocode}
                          % lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
                          % we see a ). If we do, we then loop until no ( nor ) is to be found.|
                          % begin{macrocode}
                          defXINT_isbalanced_d #1)#2%
                          {xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
                          % end{macrocode}
                          % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                          % begin{macrocode}
                          defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%

                          % New utility (expandable)
                          longdefapplyfunction #1#2)%
                          {%
                          ifcaseXINT_isbalanced_a relax #1#2)(xint_bye)xint_bye
                          expandafterapplyfunction_b
                          orexpandafterapplyfunction_again
                          elseexpandafterwe_are_doomed
                          fi {#1#2}%
                          }%
                          longdefapplyfunction_again #1{applyfunction {#1)}}%
                          longdefmy_bbye #1my_bbye {}%
                          longdefapplyfunction_b #1{applyfunction_c #1,my_bbye,}%
                          longdefapplyfunction_c #1({applyfunction_d #1{}{}}%
                          % we will take care of brace removal another day
                          longdefapplyfunction_d #1#2#3#4,%
                          {%
                          ifcaseXINT_isbalanced_a relax #3#4(xint_bye)xint_bye
                          expandafterapplyfunction_e
                          orexpandafterapplyfunction_d_again
                          elseexpandafterwe_are_doomed
                          fi #1{#2}{#3}{#4}%
                          }%
                          longdefapplyfunction_d_again #1#2#3#4%
                          {%
                          applyfunction_d #1{#2}{#3#4,}%
                          }%
                          longdefapplyfunction_e #1#2#3#4%
                          {%
                          my_bbye#4applyfunction_finishmy_bbye
                          applyfunction_g #1{#2}{#3#4}%
                          }%
                          longdefapplyfunction_g #1#2#3{applyfunction_d #1{#2{#3}}{}}%
                          longdefapplyfunction_finishmy_bbyeapplyfunction_g #1#2#3{#1#2}%

                          catcode`_ 8

                          %% USAGE
                          % "functions" to be used as foo(a,b,c,...)
                          % Syntax: applyfunctionnondelimitedmacro
                          % Number of arguments is determined dynamically (at most 9)
                          makeatletter
                          newcommandtwomate{applyfunctiontwomate@macro}
                          newcommandpwr{applyfunctionpwr@macro}
                          newcommandtwoclmn{applyfunctiontwoclmn@macro}
                          % define here the **non-delimited** auxiliary macros
                          newcommandtwomate@macro[4]{begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                          newcommandpwr@macro[1]{^{#1}}
                          newcommandtwoclmn@macro[2]{begin{pmatrix}#1\#2end{pmatrix}}
                          makeatother


                          %% TESTING NESTING
                          makeatletter
                          newcommandfoo{applyfunctionfoo@macro}
                          newcommandfoo@macro[4]{left[#1+#2+#3+#4right]}
                          letBarrelax
                          newcommandBar{applyfunctionBar@macro}
                          newcommandBar@macro[3]{left(#1*#2*#3right)}
                          makeatother

                          delimiterfactor1001

                          begin{document}

                          [
                          twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                          ]
                          [
                          twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
                          + frac25 t epwr(2t))
                          ]
                          [foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))]
                          end{document}


                          enter image description here






                          share|improve this answer

























                            up vote
                            2
                            down vote










                            up vote
                            2
                            down vote









                            original answer



                            Here is a way to define macros fetching their arguments like "functions" in many programming language.



                            It is lifted from the xintexpr code.



                            I had a bit forgotten the details, and left the code comments of XINT_isbalanced_a for those interested.



                            now that things come back more to my memory: of course comma separation of arguments will cause further issues. The xintexpr parser does not use at all this mechanism for implementing comma separated arguments of "functions". The mechanism as here is applied only for things such as seq(<expression>, x=1..10) where the <expression> if fetched as delimited by a comma, and then the balancing test is applied to it in case it was for example seq(myfunction(x,x^2),x=1..10) where the first comma would have been intially mistakendly taken as delimiter, but then the code realizes it is not balanced so it goes further.



                            thus, now that I think about it, nesting here would need checking the arguments picked up by comma delimited macros are balanced with respect to parentheses. I have not applied it yet, as the poor man approach here is still very low-weight and is enough for the OP use cases



                            See below how applyfunction is to be used.



                            (but as I explained in paragraphs above this is not provided as a nestable thing, only "functions" with 1 argument can be nested inside others; perhaps I will edit later to provide fuller solution).



                            Thus this is a no-package solution.



                            documentclass{article}

                            % copy over some utility code from package xintexpr
                            catcode`_ 11

                            makeatletter
                            letxint_c_monem@ne
                            letxint_c_z@
                            letxint_c_i@ne
                            longdefxint_bye #1xint_bye {}%
                            makeatother
                            % % end{macrocode}
                            % subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
                            % lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
                            % it, to @ne if opening ( had no closing ) matching it, to z@ if expression
                            % was balanced.|
                            % begin{macrocode}
                            % use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
                            defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
                            defXINT_isbalanced_b #1)#2%
                            {xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
                            % end{macrocode}
                            % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                            % begin{macrocode}
                            defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
                            % end{macrocode}
                            % lverb|#2 was xint_bye, was there a ) in original #1?|
                            % begin{macrocode}
                            defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                            {xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
                            % end{macrocode}
                            % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                            % begin{macrocode}
                            defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
                            % end{macrocode}
                            % lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
                            % we see a ). If we do, we then loop until no ( nor ) is to be found.|
                            % begin{macrocode}
                            defXINT_isbalanced_d #1)#2%
                            {xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
                            % end{macrocode}
                            % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                            % begin{macrocode}
                            defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%

                            % Define a utility to apply a "function", comma separated arguments
                            defapplyfunction #1(#2)%
                            {%
                            ifcaseXINT_isbalanced_a relax #1#2(xint_bye)xint_bye
                            expandafterapplyfunction_doit
                            orexpandafterapplyfunction_again
                            elseexpandafterwe_are_doomed
                            fi {#1#2}%
                            }%
                            defapplyfunction_doit #1{#1,}
                            defapplyfunction_again #1{applyfunction {#1)}(}

                            catcode`_ 8

                            usepackage{amsmath}


                            makeatletter

                            % function wrappers
                            deftwomate{applyfunctiontwomate@csv}
                            defpwr{applyfunctionpwr@csv}
                            deftwoclmn{applyfunctiontwoclmn@csv}

                            % define macros with comma delimited arguments
                            deftwomate@csv#1,#2,#3,#4,{begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                            defpwr@csv#1,{^{#1}}
                            deftwoclmn@csv#1,#2,{begin{pmatrix}#1\#2end{pmatrix}}
                            %

                            makeatother

                            begin{document}

                            [
                            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                            ]
                            [
                            twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
                            + frac25 t epwr(2t))
                            ]
                            end{document}


                            enter image description here



                            updated answer



                            Original code allowed only nesting of "function" with one-argument inside other "functions".



                            Updated code makes more general nesting possible, we will test it with this input



                            foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))


                            and it works.



                            Notice that this code works only by expansion.



                            Code:



                            documentclass{article}
                            usepackage{amsmath}

                            % copy over some utility code from package xintexpr
                            catcode`_ 11

                            makeatletter
                            letxint_c_monem@ne
                            letxint_c_z@
                            letxint_c_i@ne
                            longdefxint_bye #1xint_bye {}%
                            makeatother
                            % NOTICE THAT ALL MACROS NEXT SHOULD BE MADE `long` ARGUABLY
                            % IT WAS NOT NEEDED IN XINTEXPR CONTEXT
                            % % end{macrocode}
                            % subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
                            % lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
                            % it, to @ne if opening ( had no closing ) matching it, to z@ if expression
                            % was balanced.|
                            % begin{macrocode}
                            % use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
                            defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
                            defXINT_isbalanced_b #1)#2%
                            {xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
                            % end{macrocode}
                            % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                            % begin{macrocode}
                            defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
                            % end{macrocode}
                            % lverb|#2 was xint_bye, was there a ) in original #1?|
                            % begin{macrocode}
                            defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                            {xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
                            % end{macrocode}
                            % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                            % begin{macrocode}
                            defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
                            % end{macrocode}
                            % lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
                            % we see a ). If we do, we then loop until no ( nor ) is to be found.|
                            % begin{macrocode}
                            defXINT_isbalanced_d #1)#2%
                            {xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
                            % end{macrocode}
                            % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                            % begin{macrocode}
                            defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%

                            % New utility (expandable)
                            longdefapplyfunction #1#2)%
                            {%
                            ifcaseXINT_isbalanced_a relax #1#2)(xint_bye)xint_bye
                            expandafterapplyfunction_b
                            orexpandafterapplyfunction_again
                            elseexpandafterwe_are_doomed
                            fi {#1#2}%
                            }%
                            longdefapplyfunction_again #1{applyfunction {#1)}}%
                            longdefmy_bbye #1my_bbye {}%
                            longdefapplyfunction_b #1{applyfunction_c #1,my_bbye,}%
                            longdefapplyfunction_c #1({applyfunction_d #1{}{}}%
                            % we will take care of brace removal another day
                            longdefapplyfunction_d #1#2#3#4,%
                            {%
                            ifcaseXINT_isbalanced_a relax #3#4(xint_bye)xint_bye
                            expandafterapplyfunction_e
                            orexpandafterapplyfunction_d_again
                            elseexpandafterwe_are_doomed
                            fi #1{#2}{#3}{#4}%
                            }%
                            longdefapplyfunction_d_again #1#2#3#4%
                            {%
                            applyfunction_d #1{#2}{#3#4,}%
                            }%
                            longdefapplyfunction_e #1#2#3#4%
                            {%
                            my_bbye#4applyfunction_finishmy_bbye
                            applyfunction_g #1{#2}{#3#4}%
                            }%
                            longdefapplyfunction_g #1#2#3{applyfunction_d #1{#2{#3}}{}}%
                            longdefapplyfunction_finishmy_bbyeapplyfunction_g #1#2#3{#1#2}%

                            catcode`_ 8

                            %% USAGE
                            % "functions" to be used as foo(a,b,c,...)
                            % Syntax: applyfunctionnondelimitedmacro
                            % Number of arguments is determined dynamically (at most 9)
                            makeatletter
                            newcommandtwomate{applyfunctiontwomate@macro}
                            newcommandpwr{applyfunctionpwr@macro}
                            newcommandtwoclmn{applyfunctiontwoclmn@macro}
                            % define here the **non-delimited** auxiliary macros
                            newcommandtwomate@macro[4]{begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                            newcommandpwr@macro[1]{^{#1}}
                            newcommandtwoclmn@macro[2]{begin{pmatrix}#1\#2end{pmatrix}}
                            makeatother


                            %% TESTING NESTING
                            makeatletter
                            newcommandfoo{applyfunctionfoo@macro}
                            newcommandfoo@macro[4]{left[#1+#2+#3+#4right]}
                            letBarrelax
                            newcommandBar{applyfunctionBar@macro}
                            newcommandBar@macro[3]{left(#1*#2*#3right)}
                            makeatother

                            delimiterfactor1001

                            begin{document}

                            [
                            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                            ]
                            [
                            twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
                            + frac25 t epwr(2t))
                            ]
                            [foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))]
                            end{document}


                            enter image description here






                            share|improve this answer














                            original answer



                            Here is a way to define macros fetching their arguments like "functions" in many programming language.



                            It is lifted from the xintexpr code.



                            I had a bit forgotten the details, and left the code comments of XINT_isbalanced_a for those interested.



                            now that things come back more to my memory: of course comma separation of arguments will cause further issues. The xintexpr parser does not use at all this mechanism for implementing comma separated arguments of "functions". The mechanism as here is applied only for things such as seq(<expression>, x=1..10) where the <expression> if fetched as delimited by a comma, and then the balancing test is applied to it in case it was for example seq(myfunction(x,x^2),x=1..10) where the first comma would have been intially mistakendly taken as delimiter, but then the code realizes it is not balanced so it goes further.



                            thus, now that I think about it, nesting here would need checking the arguments picked up by comma delimited macros are balanced with respect to parentheses. I have not applied it yet, as the poor man approach here is still very low-weight and is enough for the OP use cases



                            See below how applyfunction is to be used.



                            (but as I explained in paragraphs above this is not provided as a nestable thing, only "functions" with 1 argument can be nested inside others; perhaps I will edit later to provide fuller solution).



                            Thus this is a no-package solution.



                            documentclass{article}

                            % copy over some utility code from package xintexpr
                            catcode`_ 11

                            makeatletter
                            letxint_c_monem@ne
                            letxint_c_z@
                            letxint_c_i@ne
                            longdefxint_bye #1xint_bye {}%
                            makeatother
                            % % end{macrocode}
                            % subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
                            % lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
                            % it, to @ne if opening ( had no closing ) matching it, to z@ if expression
                            % was balanced.|
                            % begin{macrocode}
                            % use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
                            defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
                            defXINT_isbalanced_b #1)#2%
                            {xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
                            % end{macrocode}
                            % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                            % begin{macrocode}
                            defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
                            % end{macrocode}
                            % lverb|#2 was xint_bye, was there a ) in original #1?|
                            % begin{macrocode}
                            defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                            {xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
                            % end{macrocode}
                            % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                            % begin{macrocode}
                            defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
                            % end{macrocode}
                            % lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
                            % we see a ). If we do, we then loop until no ( nor ) is to be found.|
                            % begin{macrocode}
                            defXINT_isbalanced_d #1)#2%
                            {xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
                            % end{macrocode}
                            % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                            % begin{macrocode}
                            defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%

                            % Define a utility to apply a "function", comma separated arguments
                            defapplyfunction #1(#2)%
                            {%
                            ifcaseXINT_isbalanced_a relax #1#2(xint_bye)xint_bye
                            expandafterapplyfunction_doit
                            orexpandafterapplyfunction_again
                            elseexpandafterwe_are_doomed
                            fi {#1#2}%
                            }%
                            defapplyfunction_doit #1{#1,}
                            defapplyfunction_again #1{applyfunction {#1)}(}

                            catcode`_ 8

                            usepackage{amsmath}


                            makeatletter

                            % function wrappers
                            deftwomate{applyfunctiontwomate@csv}
                            defpwr{applyfunctionpwr@csv}
                            deftwoclmn{applyfunctiontwoclmn@csv}

                            % define macros with comma delimited arguments
                            deftwomate@csv#1,#2,#3,#4,{begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                            defpwr@csv#1,{^{#1}}
                            deftwoclmn@csv#1,#2,{begin{pmatrix}#1\#2end{pmatrix}}
                            %

                            makeatother

                            begin{document}

                            [
                            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                            ]
                            [
                            twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
                            + frac25 t epwr(2t))
                            ]
                            end{document}


                            enter image description here



                            updated answer



                            Original code allowed only nesting of "function" with one-argument inside other "functions".



                            Updated code makes more general nesting possible, we will test it with this input



                            foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))


                            and it works.



                            Notice that this code works only by expansion.



                            Code:



                            documentclass{article}
                            usepackage{amsmath}

                            % copy over some utility code from package xintexpr
                            catcode`_ 11

                            makeatletter
                            letxint_c_monem@ne
                            letxint_c_z@
                            letxint_c_i@ne
                            longdefxint_bye #1xint_bye {}%
                            makeatother
                            % NOTICE THAT ALL MACROS NEXT SHOULD BE MADE `long` ARGUABLY
                            % IT WAS NOT NEEDED IN XINTEXPR CONTEXT
                            % % end{macrocode}
                            % subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
                            % lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
                            % it, to @ne if opening ( had no closing ) matching it, to z@ if expression
                            % was balanced.|
                            % begin{macrocode}
                            % use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
                            defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
                            defXINT_isbalanced_b #1)#2%
                            {xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
                            % end{macrocode}
                            % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                            % begin{macrocode}
                            defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
                            % end{macrocode}
                            % lverb|#2 was xint_bye, was there a ) in original #1?|
                            % begin{macrocode}
                            defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                            {xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
                            % end{macrocode}
                            % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                            % begin{macrocode}
                            defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
                            % end{macrocode}
                            % lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
                            % we see a ). If we do, we then loop until no ( nor ) is to be found.|
                            % begin{macrocode}
                            defXINT_isbalanced_d #1)#2%
                            {xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
                            % end{macrocode}
                            % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                            % begin{macrocode}
                            defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%

                            % New utility (expandable)
                            longdefapplyfunction #1#2)%
                            {%
                            ifcaseXINT_isbalanced_a relax #1#2)(xint_bye)xint_bye
                            expandafterapplyfunction_b
                            orexpandafterapplyfunction_again
                            elseexpandafterwe_are_doomed
                            fi {#1#2}%
                            }%
                            longdefapplyfunction_again #1{applyfunction {#1)}}%
                            longdefmy_bbye #1my_bbye {}%
                            longdefapplyfunction_b #1{applyfunction_c #1,my_bbye,}%
                            longdefapplyfunction_c #1({applyfunction_d #1{}{}}%
                            % we will take care of brace removal another day
                            longdefapplyfunction_d #1#2#3#4,%
                            {%
                            ifcaseXINT_isbalanced_a relax #3#4(xint_bye)xint_bye
                            expandafterapplyfunction_e
                            orexpandafterapplyfunction_d_again
                            elseexpandafterwe_are_doomed
                            fi #1{#2}{#3}{#4}%
                            }%
                            longdefapplyfunction_d_again #1#2#3#4%
                            {%
                            applyfunction_d #1{#2}{#3#4,}%
                            }%
                            longdefapplyfunction_e #1#2#3#4%
                            {%
                            my_bbye#4applyfunction_finishmy_bbye
                            applyfunction_g #1{#2}{#3#4}%
                            }%
                            longdefapplyfunction_g #1#2#3{applyfunction_d #1{#2{#3}}{}}%
                            longdefapplyfunction_finishmy_bbyeapplyfunction_g #1#2#3{#1#2}%

                            catcode`_ 8

                            %% USAGE
                            % "functions" to be used as foo(a,b,c,...)
                            % Syntax: applyfunctionnondelimitedmacro
                            % Number of arguments is determined dynamically (at most 9)
                            makeatletter
                            newcommandtwomate{applyfunctiontwomate@macro}
                            newcommandpwr{applyfunctionpwr@macro}
                            newcommandtwoclmn{applyfunctiontwoclmn@macro}
                            % define here the **non-delimited** auxiliary macros
                            newcommandtwomate@macro[4]{begin{pmatrix}#1&#2\#3&#4end{pmatrix}}
                            newcommandpwr@macro[1]{^{#1}}
                            newcommandtwoclmn@macro[2]{begin{pmatrix}#1\#2end{pmatrix}}
                            makeatother


                            %% TESTING NESTING
                            makeatletter
                            newcommandfoo{applyfunctionfoo@macro}
                            newcommandfoo@macro[4]{left[#1+#2+#3+#4right]}
                            letBarrelax
                            newcommandBar{applyfunctionBar@macro}
                            newcommandBar@macro[3]{left(#1*#2*#3right)}
                            makeatother

                            delimiterfactor1001

                            begin{document}

                            [
                            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                            ]
                            [
                            twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
                            + frac25 t epwr(2t))
                            ]
                            [foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))]
                            end{document}


                            enter image description here







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited 8 hours ago

























                            answered 15 hours ago









                            jfbu

                            43.9k65142




                            43.9k65142






















                                Hossmeister is a new contributor. Be nice, and check out our Code of Conduct.










                                 

                                draft saved


                                draft discarded


















                                Hossmeister is a new contributor. Be nice, and check out our Code of Conduct.













                                Hossmeister is a new contributor. Be nice, and check out our Code of Conduct.












                                Hossmeister is a new contributor. Be nice, and check out our Code of Conduct.















                                 


                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f459229%2fproblems-with-def%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest




















































































                                Popular posts from this blog

                                Full-time equivalent

                                Bicuculline

                                さくらももこ