Problems with def









up vote
7
down vote

favorite












I have created the following macros in LaTeX:



deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
defpwr(#1)^#1
deftwoclmn(#1,#2)beginpmatrix#1\#2endpmatrix


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(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(2t) + frac25 t epwr(2t))$$


But the following does:



$$twoclmn(frac625e^2t-frac15te^2t,-frac225e^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
    15 hours ago














up vote
7
down vote

favorite












I have created the following macros in LaTeX:



deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
defpwr(#1)^#1
deftwoclmn(#1,#2)beginpmatrix#1\#2endpmatrix


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(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(2t) + frac25 t epwr(2t))$$


But the following does:



$$twoclmn(frac625e^2t-frac15te^2t,-frac225e^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
    15 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)beginpmatrix#1&#2\#3&#4endpmatrix
defpwr(#1)^#1
deftwoclmn(#1,#2)beginpmatrix#1\#2endpmatrix


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(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(2t) + frac25 t epwr(2t))$$


But the following does:



$$twoclmn(frac625e^2t-frac15te^2t,-frac225e^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)beginpmatrix#1&#2\#3&#4endpmatrix
defpwr(#1)^#1
deftwoclmn(#1,#2)beginpmatrix#1\#2endpmatrix


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(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(2t) + frac25 t epwr(2t))$$


But the following does:



$$twoclmn(frac625e^2t-frac15te^2t,-frac225e^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
    15 hours ago
















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















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




Since you're using LaTeX, please consider using [ ... ] instead of $$ ... $$, as the latter causes some inconsistencies.
– AJFarmar
15 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.



documentclassarticle
usepackageamsmath
usepackagexparse

NewDocumentCommandtwomate>SplitArgument3,r()%
maketwomate#1%

NewDocumentCommandmaketwomatemmmm%
beginpmatrix#1&#2\#3&#4endpmatrix%

NewDocumentCommandpwrr()^#1

begindocument

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

enddocument


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



documentclassarticle
usepackageamsmath
usepackagexparse

NewDocumentCommandtwomate>SplitArgument3,m%
maketwomate#1%

NewDocumentCommandmaketwomatemmmm%
beginpmatrix#1&#2\#3&#4endpmatrix%

NewDocumentCommandpwrm^#1

begindocument

[
twomate3epwr-3t,epwr2t,-epwr-3t,-2epwr2t
]

enddocument


enter image description here






share|improve this answer




















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










  • @jfbu Yes, but why? There's no advantage whatsoever over braces.
    – egreg
    12 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
    12 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
    11 hours ago










  • @jfbu Without seeing how you define foo, bar and baz it's just guesswork.
    – egreg
    11 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:



documentclassarticle

usepackageamsmath

deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
defpwr(#1)^#1

begindocument

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

enddocument


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):



    documentclassarticle
    usepackageamsmath

    deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
    defpwr(#1)^#1
    deftwoclmn(#1,#2)beginpmatrix#1\#2endpmatrix

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


    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.



      documentclassarticle

      % 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
      % % endmacrocode
      % subsubsectioncshXINT_isbalanced_a for cshnolabelXINT_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.|
      % beginmacrocode
      % 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 %
      % endmacrocode
      % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
      % beginmacrocode
      defXINT_isbalanced_error #1)xint_bye xint_c_mone%
      % endmacrocode
      % lverb|#2 was xint_bye, was there a ) in original #1?|
      % beginmacrocode
      defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
      xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1%
      % endmacrocode
      % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
      % beginmacrocode
      defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye xint_c_ %
      % endmacrocode
      % 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.|
      % beginmacrocode
      defXINT_isbalanced_d #1)#2%
      xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2%
      % endmacrocode
      % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
      % beginmacrocode
      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 #1applyfunction #1)(

      catcode`_ 8

      usepackageamsmath


      makeatletter

      % function wrappers
      deftwomateapplyfunctiontwomate@csv
      defpwrapplyfunctionpwr@csv
      deftwoclmnapplyfunctiontwoclmn@csv

      % define macros with comma delimited arguments
      deftwomate@csv#1,#2,#3,#4,beginpmatrix#1&#2\#3&#4endpmatrix
      defpwr@csv#1,^#1
      deftwoclmn@csv#1,#2,beginpmatrix#1\#2endpmatrix
      %

      makeatother

      begindocument

      [
      twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
      ]
      [
      twoclmn(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(2t)
      + frac25 t epwr(2t))
      ]
      enddocument


      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:



      documentclassarticle
      usepackageamsmath

      % 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
      % % endmacrocode
      % subsubsectioncshXINT_isbalanced_a for cshnolabelXINT_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.|
      % beginmacrocode
      % 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 %
      % endmacrocode
      % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
      % beginmacrocode
      defXINT_isbalanced_error #1)xint_bye xint_c_mone%
      % endmacrocode
      % lverb|#2 was xint_bye, was there a ) in original #1?|
      % beginmacrocode
      defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
      xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1%
      % endmacrocode
      % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
      % beginmacrocode
      defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye xint_c_ %
      % endmacrocode
      % 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.|
      % beginmacrocode
      defXINT_isbalanced_d #1)#2%
      xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2%
      % endmacrocode
      % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
      % beginmacrocode
      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 #1applyfunction #1)%
      longdefmy_bbye #1my_bbye %
      longdefapplyfunction_b #1applyfunction_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#3applyfunction_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
      newcommandtwomateapplyfunctiontwomate@macro
      newcommandpwrapplyfunctionpwr@macro
      newcommandtwoclmnapplyfunctiontwoclmn@macro
      % define here the **non-delimited** auxiliary macros
      newcommandtwomate@macro[4]beginpmatrix#1&#2\#3&#4endpmatrix
      newcommandpwr@macro[1]^#1
      newcommandtwoclmn@macro[2]beginpmatrix#1\#2endpmatrix
      makeatother


      %% TESTING NESTING
      makeatletter
      newcommandfooapplyfunctionfoo@macro
      newcommandfoo@macro[4]left[#1+#2+#3+#4right]
      letBarrelax
      newcommandBarapplyfunctionBar@macro
      newcommandBar@macro[3]left(#1*#2*#3right)
      makeatother

      delimiterfactor1001

      begindocument

      [
      twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
      ]
      [
      twoclmn(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(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))]
      enddocument


      enter image description here






      share|improve this answer






















        Your Answer








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

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

        else
        createEditor();

        );

        function createEditor()
        StackExchange.prepareEditor(
        heartbeatType: 'answer',
        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.



        documentclassarticle
        usepackageamsmath
        usepackagexparse

        NewDocumentCommandtwomate>SplitArgument3,r()%
        maketwomate#1%

        NewDocumentCommandmaketwomatemmmm%
        beginpmatrix#1&#2\#3&#4endpmatrix%

        NewDocumentCommandpwrr()^#1

        begindocument

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

        enddocument


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



        documentclassarticle
        usepackageamsmath
        usepackagexparse

        NewDocumentCommandtwomate>SplitArgument3,m%
        maketwomate#1%

        NewDocumentCommandmaketwomatemmmm%
        beginpmatrix#1&#2\#3&#4endpmatrix%

        NewDocumentCommandpwrm^#1

        begindocument

        [
        twomate3epwr-3t,epwr2t,-epwr-3t,-2epwr2t
        ]

        enddocument


        enter image description here






        share|improve this answer




















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










        • @jfbu Yes, but why? There's no advantage whatsoever over braces.
          – egreg
          12 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
          12 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
          11 hours ago










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














        up vote
        10
        down vote



        accepted










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



        documentclassarticle
        usepackageamsmath
        usepackagexparse

        NewDocumentCommandtwomate>SplitArgument3,r()%
        maketwomate#1%

        NewDocumentCommandmaketwomatemmmm%
        beginpmatrix#1&#2\#3&#4endpmatrix%

        NewDocumentCommandpwrr()^#1

        begindocument

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

        enddocument


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



        documentclassarticle
        usepackageamsmath
        usepackagexparse

        NewDocumentCommandtwomate>SplitArgument3,m%
        maketwomate#1%

        NewDocumentCommandmaketwomatemmmm%
        beginpmatrix#1&#2\#3&#4endpmatrix%

        NewDocumentCommandpwrm^#1

        begindocument

        [
        twomate3epwr-3t,epwr2t,-epwr-3t,-2epwr2t
        ]

        enddocument


        enter image description here






        share|improve this answer




















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










        • @jfbu Yes, but why? There's no advantage whatsoever over braces.
          – egreg
          12 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
          12 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
          11 hours ago










        • @jfbu Without seeing how you define foo, bar and baz it's just guesswork.
          – egreg
          11 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.



        documentclassarticle
        usepackageamsmath
        usepackagexparse

        NewDocumentCommandtwomate>SplitArgument3,r()%
        maketwomate#1%

        NewDocumentCommandmaketwomatemmmm%
        beginpmatrix#1&#2\#3&#4endpmatrix%

        NewDocumentCommandpwrr()^#1

        begindocument

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

        enddocument


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



        documentclassarticle
        usepackageamsmath
        usepackagexparse

        NewDocumentCommandtwomate>SplitArgument3,m%
        maketwomate#1%

        NewDocumentCommandmaketwomatemmmm%
        beginpmatrix#1&#2\#3&#4endpmatrix%

        NewDocumentCommandpwrm^#1

        begindocument

        [
        twomate3epwr-3t,epwr2t,-epwr-3t,-2epwr2t
        ]

        enddocument


        enter image description here






        share|improve this answer












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



        documentclassarticle
        usepackageamsmath
        usepackagexparse

        NewDocumentCommandtwomate>SplitArgument3,r()%
        maketwomate#1%

        NewDocumentCommandmaketwomatemmmm%
        beginpmatrix#1&#2\#3&#4endpmatrix%

        NewDocumentCommandpwrr()^#1

        begindocument

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

        enddocument


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



        documentclassarticle
        usepackageamsmath
        usepackagexparse

        NewDocumentCommandtwomate>SplitArgument3,m%
        maketwomate#1%

        NewDocumentCommandmaketwomatemmmm%
        beginpmatrix#1&#2\#3&#4endpmatrix%

        NewDocumentCommandpwrm^#1

        begindocument

        [
        twomate3epwr-3t,epwr2t,-epwr-3t,-2epwr2t
        ]

        enddocument


        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
          12 hours ago










        • @jfbu Yes, but why? There's no advantage whatsoever over braces.
          – egreg
          12 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
          12 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
          11 hours ago










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
















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










        • @jfbu Yes, but why? There's no advantage whatsoever over braces.
          – egreg
          12 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
          12 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
          11 hours ago










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















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




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












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




        @jfbu Yes, but why? There's no advantage whatsoever over braces.
        – egreg
        12 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
        12 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
        12 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
        11 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
        11 hours ago












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




        @jfbu Without seeing how you define foo, bar and baz it's just guesswork.
        – egreg
        11 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:



        documentclassarticle

        usepackageamsmath

        deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
        defpwr(#1)^#1

        begindocument

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

        enddocument


        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:



          documentclassarticle

          usepackageamsmath

          deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
          defpwr(#1)^#1

          begindocument

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

          enddocument


          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:



            documentclassarticle

            usepackageamsmath

            deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
            defpwr(#1)^#1

            begindocument

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

            enddocument


            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:



            documentclassarticle

            usepackageamsmath

            deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
            defpwr(#1)^#1

            begindocument

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

            enddocument


            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):



                documentclassarticle
                usepackageamsmath

                deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
                defpwr(#1)^#1
                deftwoclmn(#1,#2)beginpmatrix#1\#2endpmatrix

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


                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):



                  documentclassarticle
                  usepackageamsmath

                  deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
                  defpwr(#1)^#1
                  deftwoclmn(#1,#2)beginpmatrix#1\#2endpmatrix

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


                  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):



                    documentclassarticle
                    usepackageamsmath

                    deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
                    defpwr(#1)^#1
                    deftwoclmn(#1,#2)beginpmatrix#1\#2endpmatrix

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


                    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):



                    documentclassarticle
                    usepackageamsmath

                    deftwomate(#1,#2,#3,#4)beginpmatrix#1&#2\#3&#4endpmatrix
                    defpwr(#1)^#1
                    deftwoclmn(#1,#2)beginpmatrix#1\#2endpmatrix

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


                    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.



                        documentclassarticle

                        % 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
                        % % endmacrocode
                        % subsubsectioncshXINT_isbalanced_a for cshnolabelXINT_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.|
                        % beginmacrocode
                        % 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 %
                        % endmacrocode
                        % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                        % beginmacrocode
                        defXINT_isbalanced_error #1)xint_bye xint_c_mone%
                        % endmacrocode
                        % lverb|#2 was xint_bye, was there a ) in original #1?|
                        % beginmacrocode
                        defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                        xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1%
                        % endmacrocode
                        % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                        % beginmacrocode
                        defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye xint_c_ %
                        % endmacrocode
                        % 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.|
                        % beginmacrocode
                        defXINT_isbalanced_d #1)#2%
                        xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2%
                        % endmacrocode
                        % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                        % beginmacrocode
                        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 #1applyfunction #1)(

                        catcode`_ 8

                        usepackageamsmath


                        makeatletter

                        % function wrappers
                        deftwomateapplyfunctiontwomate@csv
                        defpwrapplyfunctionpwr@csv
                        deftwoclmnapplyfunctiontwoclmn@csv

                        % define macros with comma delimited arguments
                        deftwomate@csv#1,#2,#3,#4,beginpmatrix#1&#2\#3&#4endpmatrix
                        defpwr@csv#1,^#1
                        deftwoclmn@csv#1,#2,beginpmatrix#1\#2endpmatrix
                        %

                        makeatother

                        begindocument

                        [
                        twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                        ]
                        [
                        twoclmn(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(2t)
                        + frac25 t epwr(2t))
                        ]
                        enddocument


                        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:



                        documentclassarticle
                        usepackageamsmath

                        % 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
                        % % endmacrocode
                        % subsubsectioncshXINT_isbalanced_a for cshnolabelXINT_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.|
                        % beginmacrocode
                        % 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 %
                        % endmacrocode
                        % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                        % beginmacrocode
                        defXINT_isbalanced_error #1)xint_bye xint_c_mone%
                        % endmacrocode
                        % lverb|#2 was xint_bye, was there a ) in original #1?|
                        % beginmacrocode
                        defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                        xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1%
                        % endmacrocode
                        % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                        % beginmacrocode
                        defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye xint_c_ %
                        % endmacrocode
                        % 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.|
                        % beginmacrocode
                        defXINT_isbalanced_d #1)#2%
                        xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2%
                        % endmacrocode
                        % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                        % beginmacrocode
                        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 #1applyfunction #1)%
                        longdefmy_bbye #1my_bbye %
                        longdefapplyfunction_b #1applyfunction_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#3applyfunction_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
                        newcommandtwomateapplyfunctiontwomate@macro
                        newcommandpwrapplyfunctionpwr@macro
                        newcommandtwoclmnapplyfunctiontwoclmn@macro
                        % define here the **non-delimited** auxiliary macros
                        newcommandtwomate@macro[4]beginpmatrix#1&#2\#3&#4endpmatrix
                        newcommandpwr@macro[1]^#1
                        newcommandtwoclmn@macro[2]beginpmatrix#1\#2endpmatrix
                        makeatother


                        %% TESTING NESTING
                        makeatletter
                        newcommandfooapplyfunctionfoo@macro
                        newcommandfoo@macro[4]left[#1+#2+#3+#4right]
                        letBarrelax
                        newcommandBarapplyfunctionBar@macro
                        newcommandBar@macro[3]left(#1*#2*#3right)
                        makeatother

                        delimiterfactor1001

                        begindocument

                        [
                        twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                        ]
                        [
                        twoclmn(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(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))]
                        enddocument


                        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.



                          documentclassarticle

                          % 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
                          % % endmacrocode
                          % subsubsectioncshXINT_isbalanced_a for cshnolabelXINT_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.|
                          % beginmacrocode
                          % 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 %
                          % endmacrocode
                          % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                          % beginmacrocode
                          defXINT_isbalanced_error #1)xint_bye xint_c_mone%
                          % endmacrocode
                          % lverb|#2 was xint_bye, was there a ) in original #1?|
                          % beginmacrocode
                          defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                          xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1%
                          % endmacrocode
                          % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                          % beginmacrocode
                          defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye xint_c_ %
                          % endmacrocode
                          % 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.|
                          % beginmacrocode
                          defXINT_isbalanced_d #1)#2%
                          xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2%
                          % endmacrocode
                          % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                          % beginmacrocode
                          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 #1applyfunction #1)(

                          catcode`_ 8

                          usepackageamsmath


                          makeatletter

                          % function wrappers
                          deftwomateapplyfunctiontwomate@csv
                          defpwrapplyfunctionpwr@csv
                          deftwoclmnapplyfunctiontwoclmn@csv

                          % define macros with comma delimited arguments
                          deftwomate@csv#1,#2,#3,#4,beginpmatrix#1&#2\#3&#4endpmatrix
                          defpwr@csv#1,^#1
                          deftwoclmn@csv#1,#2,beginpmatrix#1\#2endpmatrix
                          %

                          makeatother

                          begindocument

                          [
                          twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                          ]
                          [
                          twoclmn(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(2t)
                          + frac25 t epwr(2t))
                          ]
                          enddocument


                          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:



                          documentclassarticle
                          usepackageamsmath

                          % 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
                          % % endmacrocode
                          % subsubsectioncshXINT_isbalanced_a for cshnolabelXINT_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.|
                          % beginmacrocode
                          % 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 %
                          % endmacrocode
                          % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                          % beginmacrocode
                          defXINT_isbalanced_error #1)xint_bye xint_c_mone%
                          % endmacrocode
                          % lverb|#2 was xint_bye, was there a ) in original #1?|
                          % beginmacrocode
                          defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                          xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1%
                          % endmacrocode
                          % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                          % beginmacrocode
                          defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye xint_c_ %
                          % endmacrocode
                          % 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.|
                          % beginmacrocode
                          defXINT_isbalanced_d #1)#2%
                          xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2%
                          % endmacrocode
                          % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                          % beginmacrocode
                          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 #1applyfunction #1)%
                          longdefmy_bbye #1my_bbye %
                          longdefapplyfunction_b #1applyfunction_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#3applyfunction_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
                          newcommandtwomateapplyfunctiontwomate@macro
                          newcommandpwrapplyfunctionpwr@macro
                          newcommandtwoclmnapplyfunctiontwoclmn@macro
                          % define here the **non-delimited** auxiliary macros
                          newcommandtwomate@macro[4]beginpmatrix#1&#2\#3&#4endpmatrix
                          newcommandpwr@macro[1]^#1
                          newcommandtwoclmn@macro[2]beginpmatrix#1\#2endpmatrix
                          makeatother


                          %% TESTING NESTING
                          makeatletter
                          newcommandfooapplyfunctionfoo@macro
                          newcommandfoo@macro[4]left[#1+#2+#3+#4right]
                          letBarrelax
                          newcommandBarapplyfunctionBar@macro
                          newcommandBar@macro[3]left(#1*#2*#3right)
                          makeatother

                          delimiterfactor1001

                          begindocument

                          [
                          twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                          ]
                          [
                          twoclmn(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(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))]
                          enddocument


                          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.



                            documentclassarticle

                            % 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
                            % % endmacrocode
                            % subsubsectioncshXINT_isbalanced_a for cshnolabelXINT_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.|
                            % beginmacrocode
                            % 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 %
                            % endmacrocode
                            % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                            % beginmacrocode
                            defXINT_isbalanced_error #1)xint_bye xint_c_mone%
                            % endmacrocode
                            % lverb|#2 was xint_bye, was there a ) in original #1?|
                            % beginmacrocode
                            defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                            xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1%
                            % endmacrocode
                            % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                            % beginmacrocode
                            defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye xint_c_ %
                            % endmacrocode
                            % 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.|
                            % beginmacrocode
                            defXINT_isbalanced_d #1)#2%
                            xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2%
                            % endmacrocode
                            % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                            % beginmacrocode
                            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 #1applyfunction #1)(

                            catcode`_ 8

                            usepackageamsmath


                            makeatletter

                            % function wrappers
                            deftwomateapplyfunctiontwomate@csv
                            defpwrapplyfunctionpwr@csv
                            deftwoclmnapplyfunctiontwoclmn@csv

                            % define macros with comma delimited arguments
                            deftwomate@csv#1,#2,#3,#4,beginpmatrix#1&#2\#3&#4endpmatrix
                            defpwr@csv#1,^#1
                            deftwoclmn@csv#1,#2,beginpmatrix#1\#2endpmatrix
                            %

                            makeatother

                            begindocument

                            [
                            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                            ]
                            [
                            twoclmn(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(2t)
                            + frac25 t epwr(2t))
                            ]
                            enddocument


                            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:



                            documentclassarticle
                            usepackageamsmath

                            % 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
                            % % endmacrocode
                            % subsubsectioncshXINT_isbalanced_a for cshnolabelXINT_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.|
                            % beginmacrocode
                            % 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 %
                            % endmacrocode
                            % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                            % beginmacrocode
                            defXINT_isbalanced_error #1)xint_bye xint_c_mone%
                            % endmacrocode
                            % lverb|#2 was xint_bye, was there a ) in original #1?|
                            % beginmacrocode
                            defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                            xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1%
                            % endmacrocode
                            % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                            % beginmacrocode
                            defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye xint_c_ %
                            % endmacrocode
                            % 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.|
                            % beginmacrocode
                            defXINT_isbalanced_d #1)#2%
                            xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2%
                            % endmacrocode
                            % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                            % beginmacrocode
                            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 #1applyfunction #1)%
                            longdefmy_bbye #1my_bbye %
                            longdefapplyfunction_b #1applyfunction_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#3applyfunction_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
                            newcommandtwomateapplyfunctiontwomate@macro
                            newcommandpwrapplyfunctionpwr@macro
                            newcommandtwoclmnapplyfunctiontwoclmn@macro
                            % define here the **non-delimited** auxiliary macros
                            newcommandtwomate@macro[4]beginpmatrix#1&#2\#3&#4endpmatrix
                            newcommandpwr@macro[1]^#1
                            newcommandtwoclmn@macro[2]beginpmatrix#1\#2endpmatrix
                            makeatother


                            %% TESTING NESTING
                            makeatletter
                            newcommandfooapplyfunctionfoo@macro
                            newcommandfoo@macro[4]left[#1+#2+#3+#4right]
                            letBarrelax
                            newcommandBarapplyfunctionBar@macro
                            newcommandBar@macro[3]left(#1*#2*#3right)
                            makeatother

                            delimiterfactor1001

                            begindocument

                            [
                            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                            ]
                            [
                            twoclmn(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(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))]
                            enddocument


                            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.



                            documentclassarticle

                            % 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
                            % % endmacrocode
                            % subsubsectioncshXINT_isbalanced_a for cshnolabelXINT_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.|
                            % beginmacrocode
                            % 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 %
                            % endmacrocode
                            % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                            % beginmacrocode
                            defXINT_isbalanced_error #1)xint_bye xint_c_mone%
                            % endmacrocode
                            % lverb|#2 was xint_bye, was there a ) in original #1?|
                            % beginmacrocode
                            defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                            xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1%
                            % endmacrocode
                            % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                            % beginmacrocode
                            defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye xint_c_ %
                            % endmacrocode
                            % 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.|
                            % beginmacrocode
                            defXINT_isbalanced_d #1)#2%
                            xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2%
                            % endmacrocode
                            % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                            % beginmacrocode
                            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 #1applyfunction #1)(

                            catcode`_ 8

                            usepackageamsmath


                            makeatletter

                            % function wrappers
                            deftwomateapplyfunctiontwomate@csv
                            defpwrapplyfunctionpwr@csv
                            deftwoclmnapplyfunctiontwoclmn@csv

                            % define macros with comma delimited arguments
                            deftwomate@csv#1,#2,#3,#4,beginpmatrix#1&#2\#3&#4endpmatrix
                            defpwr@csv#1,^#1
                            deftwoclmn@csv#1,#2,beginpmatrix#1\#2endpmatrix
                            %

                            makeatother

                            begindocument

                            [
                            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                            ]
                            [
                            twoclmn(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(2t)
                            + frac25 t epwr(2t))
                            ]
                            enddocument


                            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:



                            documentclassarticle
                            usepackageamsmath

                            % 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
                            % % endmacrocode
                            % subsubsectioncshXINT_isbalanced_a for cshnolabelXINT_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.|
                            % beginmacrocode
                            % 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 %
                            % endmacrocode
                            % lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
                            % beginmacrocode
                            defXINT_isbalanced_error #1)xint_bye xint_c_mone%
                            % endmacrocode
                            % lverb|#2 was xint_bye, was there a ) in original #1?|
                            % beginmacrocode
                            defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
                            xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1%
                            % endmacrocode
                            % lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
                            % beginmacrocode
                            defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye xint_c_ %
                            % endmacrocode
                            % 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.|
                            % beginmacrocode
                            defXINT_isbalanced_d #1)#2%
                            xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2%
                            % endmacrocode
                            % lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
                            % beginmacrocode
                            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 #1applyfunction #1)%
                            longdefmy_bbye #1my_bbye %
                            longdefapplyfunction_b #1applyfunction_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#3applyfunction_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
                            newcommandtwomateapplyfunctiontwomate@macro
                            newcommandpwrapplyfunctionpwr@macro
                            newcommandtwoclmnapplyfunctiontwoclmn@macro
                            % define here the **non-delimited** auxiliary macros
                            newcommandtwomate@macro[4]beginpmatrix#1&#2\#3&#4endpmatrix
                            newcommandpwr@macro[1]^#1
                            newcommandtwoclmn@macro[2]beginpmatrix#1\#2endpmatrix
                            makeatother


                            %% TESTING NESTING
                            makeatletter
                            newcommandfooapplyfunctionfoo@macro
                            newcommandfoo@macro[4]left[#1+#2+#3+#4right]
                            letBarrelax
                            newcommandBarapplyfunctionBar@macro
                            newcommandBar@macro[3]left(#1*#2*#3right)
                            makeatother

                            delimiterfactor1001

                            begindocument

                            [
                            twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
                            ]
                            [
                            twoclmn(frac625epwr(2t)-frac15tepwr(2t),-frac225epwr(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))]
                            enddocument


                            enter image description here







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited 12 hours ago

























                            answered 19 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














































































                                這個網誌中的熱門文章

                                How to read a connectionString WITH PROVIDER in .NET Core?

                                Node.js Script on GitHub Pages or Amazon S3

                                Museum of Modern and Contemporary Art of Trento and Rovereto