Problems with def
up vote
7
down vote
favorite
I have created the following macros in LaTeX:
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}
Where twomate
is a 2x2 matrix, twoclmn
creates a 2x1 column vector, and pwr
is a command to raise the argument to the power.
However, if I try to do the following:
$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )$$
I get an error. However, if I replace the last entry with something that is not a def
command:
$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),5 )$$
The document complies successfully. In addition, the following does not compile successfully:
$$twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t) + frac25 t epwr(2t))$$
But the following does:
$$twoclmn(frac{6}{25}e^{2t}-frac15te^{2t},-frac{2}{25}e^{2t} + frac25 t e^{2t})$$
So the problem seems to be the nested def
commands. How may I nest def
commands, without the compiler complaining?
math-mode macros
New contributor
add a comment |
up vote
7
down vote
favorite
I have created the following macros in LaTeX:
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}
Where twomate
is a 2x2 matrix, twoclmn
creates a 2x1 column vector, and pwr
is a command to raise the argument to the power.
However, if I try to do the following:
$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )$$
I get an error. However, if I replace the last entry with something that is not a def
command:
$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),5 )$$
The document complies successfully. In addition, the following does not compile successfully:
$$twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t) + frac25 t epwr(2t))$$
But the following does:
$$twoclmn(frac{6}{25}e^{2t}-frac15te^{2t},-frac{2}{25}e^{2t} + frac25 t e^{2t})$$
So the problem seems to be the nested def
commands. How may I nest def
commands, without the compiler complaining?
math-mode macros
New contributor
Since you're using LaTeX, please consider using[ ... ]
instead of$$ ... $$
, as the latter causes some inconsistencies.
– AJFarmar
11 hours ago
add a comment |
up vote
7
down vote
favorite
up vote
7
down vote
favorite
I have created the following macros in LaTeX:
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}
Where twomate
is a 2x2 matrix, twoclmn
creates a 2x1 column vector, and pwr
is a command to raise the argument to the power.
However, if I try to do the following:
$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )$$
I get an error. However, if I replace the last entry with something that is not a def
command:
$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),5 )$$
The document complies successfully. In addition, the following does not compile successfully:
$$twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t) + frac25 t epwr(2t))$$
But the following does:
$$twoclmn(frac{6}{25}e^{2t}-frac15te^{2t},-frac{2}{25}e^{2t} + frac25 t e^{2t})$$
So the problem seems to be the nested def
commands. How may I nest def
commands, without the compiler complaining?
math-mode macros
New contributor
I have created the following macros in LaTeX:
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}
Where twomate
is a 2x2 matrix, twoclmn
creates a 2x1 column vector, and pwr
is a command to raise the argument to the power.
However, if I try to do the following:
$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )$$
I get an error. However, if I replace the last entry with something that is not a def
command:
$$twomate(3epwr(-3t),epwr(2t),-epwr(-3t),5 )$$
The document complies successfully. In addition, the following does not compile successfully:
$$twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t) + frac25 t epwr(2t))$$
But the following does:
$$twoclmn(frac{6}{25}e^{2t}-frac15te^{2t},-frac{2}{25}e^{2t} + frac25 t e^{2t})$$
So the problem seems to be the nested def
commands. How may I nest def
commands, without the compiler complaining?
math-mode macros
math-mode macros
New contributor
New contributor
New contributor
asked yesterday
Hossmeister
383
383
New contributor
New contributor
Since you're using LaTeX, please consider using[ ... ]
instead of$$ ... $$
, as the latter causes some inconsistencies.
– AJFarmar
11 hours ago
add a comment |
Since you're using LaTeX, please consider using[ ... ]
instead of$$ ... $$
, as the latter causes some inconsistencies.
– AJFarmar
11 hours ago
Since you're using LaTeX, please consider using
[ ... ]
instead of $$ ... $$
, as the latter causes some inconsistencies.– AJFarmar
11 hours ago
Since you're using LaTeX, please consider using
[ ... ]
instead of $$ ... $$
, as the latter causes some inconsistencies.– AJFarmar
11 hours ago
add a comment |
4 Answers
4
active
oldest
votes
up vote
10
down vote
accepted
You can use xparse
for this job, because the r
argument type takes care of nesting.
documentclass{article}
usepackage{amsmath}
usepackage{xparse}
NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}r()}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1\#3end{pmatrix}%
}
NewDocumentCommand{pwr}{r()}{^{#1}}
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )
]
end{document}
However, using ()
as delimiters doesn't seem a good idea. The following is as clear and behaves better with syntax coloring of front ends.
documentclass{article}
usepackage{amsmath}
usepackage{xparse}
NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}m}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1\#3end{pmatrix}%
}
NewDocumentCommand{pwr}{m}{^{#1}}
begin{document}
[
twomate{3epwr{-3t},epwr{2t},-epwr{-3t},-2epwr{2t}}
]
end{document}
can one nest like thisfoo(a,bar(b,c,d),baz(e,f),g)
?
– jfbu
8 hours ago
@jfbu Yes, but why? There's no advantage whatsoever over braces.
– egreg
8 hours ago
ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
– jfbu
8 hours ago
actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"
). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
– jfbu
7 hours ago
@jfbu Without seeing how you definefoo
,bar
andbaz
it's just guesswork.
– egreg
7 hours ago
|
show 4 more comments
up vote
9
down vote
Your def
contains a very specific sequence defined as the parameter text:
% 1 2 3 4 5
deftwomate(<1>,<2>,<3>,<4>){ ... }
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └ comma ┘ │
% └─── bracket ───┘
This parameter text is matched exactly in order (almost like a first-come-first-served style) to extract the four arguments <1>
, <2>
, <3>
and <4>
. Here's how the elements are grabbed for twomate
with the above notation:
% 1 2 3 4 5
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └────── comma ────────┘ │
% └───────────────── bracket ──────────────────┘
It should be clear that the last bracket )
isn't properly captured for pwr
. The way around it is to hide pwr(.)
from twomate
:
documentclass{article}
usepackage{amsmath}
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),{-2epwr(2t)})
]
end{document}
This solves the problem only temporarily. If you nest elements, you'll run into similar problems because of the parameter text pattern matching. In general, it is safer to group arguments using {
...}
.
add a comment |
up vote
5
down vote
TeX's delimited parameters parsing doesn't take nesting into account properly. So if you call twomate(3epwr(-3t), ...)
, the final )
for twomate
isn't found at the end of that line but at the end of pwr(-3t)
. The improperly formed call of pwr
then causes trouble.
To hide nested calls of your commands, put them into { ... }
groups (though this probably defeats the purpose):
documentclass{article}
usepackage{amsmath}
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}
begin{document}
[ twomate({3epwr(-3t)},{epwr(2t)},{-epwr(-3t)},{-2epwr(2t)}) ]
end{document}
By the way, don't use $$ ... $$
for display math environments but LaTeX's or amsmath
's variants like [ ... ]
.
add a comment |
up vote
2
down vote
original answer
Here is a way to define macros fetching their arguments like "functions" in many programming language.
It is lifted from the xintexpr
code.
I had a bit forgotten the details, and left the code comments of XINT_isbalanced_a
for those interested.
now that things come back more to my memory: of course comma separation of arguments will cause further issues. The xintexpr parser does not use at all this mechanism for implementing comma separated arguments of "functions". The mechanism as here is applied only for things such as seq(<expression>, x=1..10)
where the <expression>
if fetched as delimited by a comma, and then the balancing test is applied to it in case it was for example seq(myfunction(x,x^2),x=1..10)
where the first comma would have been intially mistakendly taken as delimiter, but then the code realizes it is not balanced so it goes further.
thus, now that I think about it, nesting here would need checking the arguments picked up by comma delimited macros are balanced with respect to parentheses. I have not applied it yet, as the poor man approach here is still very low-weight and is enough for the OP use cases
See below how applyfunction
is to be used.
(but as I explained in paragraphs above this is not provided as a nestable thing, only "functions" with 1 argument can be nested inside others; perhaps I will edit later to provide fuller solution).
Thus this is a no-package solution.
documentclass{article}
% copy over some utility code from package xintexpr
catcode`_ 11
makeatletter
letxint_c_monem@ne
letxint_c_z@
letxint_c_i@ne
longdefxint_bye #1xint_bye {}%
makeatother
% % end{macrocode}
% subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
% lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
% it, to @ne if opening ( had no closing ) matching it, to z@ if expression
% was balanced.|
% begin{macrocode}
% use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
defXINT_isbalanced_b #1)#2%
{xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
% end{macrocode}
% lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
% begin{macrocode}
defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
% end{macrocode}
% lverb|#2 was xint_bye, was there a ) in original #1?|
% begin{macrocode}
defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
{xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
% end{macrocode}
% lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
% begin{macrocode}
defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
% end{macrocode}
% lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
% we see a ). If we do, we then loop until no ( nor ) is to be found.|
% begin{macrocode}
defXINT_isbalanced_d #1)#2%
{xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
% end{macrocode}
% lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
% begin{macrocode}
defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%
% Define a utility to apply a "function", comma separated arguments
defapplyfunction #1(#2)%
{%
ifcaseXINT_isbalanced_a relax #1#2(xint_bye)xint_bye
expandafterapplyfunction_doit
orexpandafterapplyfunction_again
elseexpandafterwe_are_doomed
fi {#1#2}%
}%
defapplyfunction_doit #1{#1,}
defapplyfunction_again #1{applyfunction {#1)}(}
catcode`_ 8
usepackage{amsmath}
makeatletter
% function wrappers
deftwomate{applyfunctiontwomate@csv}
defpwr{applyfunctionpwr@csv}
deftwoclmn{applyfunctiontwoclmn@csv}
% define macros with comma delimited arguments
deftwomate@csv#1,#2,#3,#4,{begin{pmatrix}#1\#3end{pmatrix}}
defpwr@csv#1,{^{#1}}
deftwoclmn@csv#1,#2,{begin{pmatrix}#1\#2end{pmatrix}}
%
makeatother
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
]
[
twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
+ frac25 t epwr(2t))
]
end{document}
updated answer
Original code allowed only nesting of "function" with one-argument inside other "functions".
Updated code makes more general nesting possible, we will test it with this input
foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))
and it works.
Notice that this code works only by expansion.
Code:
documentclass{article}
usepackage{amsmath}
% copy over some utility code from package xintexpr
catcode`_ 11
makeatletter
letxint_c_monem@ne
letxint_c_z@
letxint_c_i@ne
longdefxint_bye #1xint_bye {}%
makeatother
% NOTICE THAT ALL MACROS NEXT SHOULD BE MADE `long` ARGUABLY
% IT WAS NOT NEEDED IN XINTEXPR CONTEXT
% % end{macrocode}
% subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
% lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
% it, to @ne if opening ( had no closing ) matching it, to z@ if expression
% was balanced.|
% begin{macrocode}
% use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
defXINT_isbalanced_b #1)#2%
{xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
% end{macrocode}
% lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
% begin{macrocode}
defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
% end{macrocode}
% lverb|#2 was xint_bye, was there a ) in original #1?|
% begin{macrocode}
defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
{xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
% end{macrocode}
% lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
% begin{macrocode}
defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
% end{macrocode}
% lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
% we see a ). If we do, we then loop until no ( nor ) is to be found.|
% begin{macrocode}
defXINT_isbalanced_d #1)#2%
{xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
% end{macrocode}
% lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
% begin{macrocode}
defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%
% New utility (expandable)
longdefapplyfunction #1#2)%
{%
ifcaseXINT_isbalanced_a relax #1#2)(xint_bye)xint_bye
expandafterapplyfunction_b
orexpandafterapplyfunction_again
elseexpandafterwe_are_doomed
fi {#1#2}%
}%
longdefapplyfunction_again #1{applyfunction {#1)}}%
longdefmy_bbye #1my_bbye {}%
longdefapplyfunction_b #1{applyfunction_c #1,my_bbye,}%
longdefapplyfunction_c #1({applyfunction_d #1{}{}}%
% we will take care of brace removal another day
longdefapplyfunction_d #1#2#3#4,%
{%
ifcaseXINT_isbalanced_a relax #3#4(xint_bye)xint_bye
expandafterapplyfunction_e
orexpandafterapplyfunction_d_again
elseexpandafterwe_are_doomed
fi #1{#2}{#3}{#4}%
}%
longdefapplyfunction_d_again #1#2#3#4%
{%
applyfunction_d #1{#2}{#3#4,}%
}%
longdefapplyfunction_e #1#2#3#4%
{%
my_bbye#4applyfunction_finishmy_bbye
applyfunction_g #1{#2}{#3#4}%
}%
longdefapplyfunction_g #1#2#3{applyfunction_d #1{#2{#3}}{}}%
longdefapplyfunction_finishmy_bbyeapplyfunction_g #1#2#3{#1#2}%
catcode`_ 8
%% USAGE
% "functions" to be used as foo(a,b,c,...)
% Syntax: applyfunctionnondelimitedmacro
% Number of arguments is determined dynamically (at most 9)
makeatletter
newcommandtwomate{applyfunctiontwomate@macro}
newcommandpwr{applyfunctionpwr@macro}
newcommandtwoclmn{applyfunctiontwoclmn@macro}
% define here the **non-delimited** auxiliary macros
newcommandtwomate@macro[4]{begin{pmatrix}#1\#3end{pmatrix}}
newcommandpwr@macro[1]{^{#1}}
newcommandtwoclmn@macro[2]{begin{pmatrix}#1\#2end{pmatrix}}
makeatother
%% TESTING NESTING
makeatletter
newcommandfoo{applyfunctionfoo@macro}
newcommandfoo@macro[4]{left[#1+#2+#3+#4right]}
letBarrelax
newcommandBar{applyfunctionBar@macro}
newcommandBar@macro[3]{left(#1*#2*#3right)}
makeatother
delimiterfactor1001
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
]
[
twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
+ frac25 t epwr(2t))
]
[foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))]
end{document}
add a comment |
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
10
down vote
accepted
You can use xparse
for this job, because the r
argument type takes care of nesting.
documentclass{article}
usepackage{amsmath}
usepackage{xparse}
NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}r()}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1\#3end{pmatrix}%
}
NewDocumentCommand{pwr}{r()}{^{#1}}
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )
]
end{document}
However, using ()
as delimiters doesn't seem a good idea. The following is as clear and behaves better with syntax coloring of front ends.
documentclass{article}
usepackage{amsmath}
usepackage{xparse}
NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}m}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1\#3end{pmatrix}%
}
NewDocumentCommand{pwr}{m}{^{#1}}
begin{document}
[
twomate{3epwr{-3t},epwr{2t},-epwr{-3t},-2epwr{2t}}
]
end{document}
can one nest like thisfoo(a,bar(b,c,d),baz(e,f),g)
?
– jfbu
8 hours ago
@jfbu Yes, but why? There's no advantage whatsoever over braces.
– egreg
8 hours ago
ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
– jfbu
8 hours ago
actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"
). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
– jfbu
7 hours ago
@jfbu Without seeing how you definefoo
,bar
andbaz
it's just guesswork.
– egreg
7 hours ago
|
show 4 more comments
up vote
10
down vote
accepted
You can use xparse
for this job, because the r
argument type takes care of nesting.
documentclass{article}
usepackage{amsmath}
usepackage{xparse}
NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}r()}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1\#3end{pmatrix}%
}
NewDocumentCommand{pwr}{r()}{^{#1}}
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )
]
end{document}
However, using ()
as delimiters doesn't seem a good idea. The following is as clear and behaves better with syntax coloring of front ends.
documentclass{article}
usepackage{amsmath}
usepackage{xparse}
NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}m}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1\#3end{pmatrix}%
}
NewDocumentCommand{pwr}{m}{^{#1}}
begin{document}
[
twomate{3epwr{-3t},epwr{2t},-epwr{-3t},-2epwr{2t}}
]
end{document}
can one nest like thisfoo(a,bar(b,c,d),baz(e,f),g)
?
– jfbu
8 hours ago
@jfbu Yes, but why? There's no advantage whatsoever over braces.
– egreg
8 hours ago
ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
– jfbu
8 hours ago
actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"
). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
– jfbu
7 hours ago
@jfbu Without seeing how you definefoo
,bar
andbaz
it's just guesswork.
– egreg
7 hours ago
|
show 4 more comments
up vote
10
down vote
accepted
up vote
10
down vote
accepted
You can use xparse
for this job, because the r
argument type takes care of nesting.
documentclass{article}
usepackage{amsmath}
usepackage{xparse}
NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}r()}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1\#3end{pmatrix}%
}
NewDocumentCommand{pwr}{r()}{^{#1}}
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )
]
end{document}
However, using ()
as delimiters doesn't seem a good idea. The following is as clear and behaves better with syntax coloring of front ends.
documentclass{article}
usepackage{amsmath}
usepackage{xparse}
NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}m}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1\#3end{pmatrix}%
}
NewDocumentCommand{pwr}{m}{^{#1}}
begin{document}
[
twomate{3epwr{-3t},epwr{2t},-epwr{-3t},-2epwr{2t}}
]
end{document}
You can use xparse
for this job, because the r
argument type takes care of nesting.
documentclass{article}
usepackage{amsmath}
usepackage{xparse}
NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}r()}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1\#3end{pmatrix}%
}
NewDocumentCommand{pwr}{r()}{^{#1}}
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t) )
]
end{document}
However, using ()
as delimiters doesn't seem a good idea. The following is as clear and behaves better with syntax coloring of front ends.
documentclass{article}
usepackage{amsmath}
usepackage{xparse}
NewDocumentCommand{twomate}{>{SplitArgument{3}{,}}m}{%
maketwomate#1%
}
NewDocumentCommand{maketwomate}{mmmm}{%
begin{pmatrix}#1\#3end{pmatrix}%
}
NewDocumentCommand{pwr}{m}{^{#1}}
begin{document}
[
twomate{3epwr{-3t},epwr{2t},-epwr{-3t},-2epwr{2t}}
]
end{document}
answered yesterday
egreg
696k8518483108
696k8518483108
can one nest like thisfoo(a,bar(b,c,d),baz(e,f),g)
?
– jfbu
8 hours ago
@jfbu Yes, but why? There's no advantage whatsoever over braces.
– egreg
8 hours ago
ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
– jfbu
8 hours ago
actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"
). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
– jfbu
7 hours ago
@jfbu Without seeing how you definefoo
,bar
andbaz
it's just guesswork.
– egreg
7 hours ago
|
show 4 more comments
can one nest like thisfoo(a,bar(b,c,d),baz(e,f),g)
?
– jfbu
8 hours ago
@jfbu Yes, but why? There's no advantage whatsoever over braces.
– egreg
8 hours ago
ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
– jfbu
8 hours ago
actually I now tried and it does not seem to work with the code you posted (LaTeX error: "xparse/split-excess-tokens"
). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.
– jfbu
7 hours ago
@jfbu Without seeing how you definefoo
,bar
andbaz
it's just guesswork.
– egreg
7 hours ago
can one nest like this
foo(a,bar(b,c,d),baz(e,f),g)
?– jfbu
8 hours ago
can one nest like this
foo(a,bar(b,c,d),baz(e,f),g)
?– jfbu
8 hours ago
@jfbu Yes, but why? There's no advantage whatsoever over braces.
– egreg
8 hours ago
@jfbu Yes, but why? There's no advantage whatsoever over braces.
– egreg
8 hours ago
ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
– jfbu
8 hours ago
ok, just curious because I am not familiar with xparse, so your first solution allows that already? (will clean up comments afterwards). I agree with what you say over input syntax.
– jfbu
8 hours ago
actually I now tried and it does not seem to work with the code you posted (
LaTeX error: "xparse/split-excess-tokens"
). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.– jfbu
7 hours ago
actually I now tried and it does not seem to work with the code you posted (
LaTeX error: "xparse/split-excess-tokens"
). So I guess you meant "yes it can be done", not "yes, it does it". Again I agree that TeX has its own syntax and trying to use another one (with all induced complications) is not the way to go for user macros.– jfbu
7 hours ago
@jfbu Without seeing how you define
foo
, bar
and baz
it's just guesswork.– egreg
7 hours ago
@jfbu Without seeing how you define
foo
, bar
and baz
it's just guesswork.– egreg
7 hours ago
|
show 4 more comments
up vote
9
down vote
Your def
contains a very specific sequence defined as the parameter text:
% 1 2 3 4 5
deftwomate(<1>,<2>,<3>,<4>){ ... }
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └ comma ┘ │
% └─── bracket ───┘
This parameter text is matched exactly in order (almost like a first-come-first-served style) to extract the four arguments <1>
, <2>
, <3>
and <4>
. Here's how the elements are grabbed for twomate
with the above notation:
% 1 2 3 4 5
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └────── comma ────────┘ │
% └───────────────── bracket ──────────────────┘
It should be clear that the last bracket )
isn't properly captured for pwr
. The way around it is to hide pwr(.)
from twomate
:
documentclass{article}
usepackage{amsmath}
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),{-2epwr(2t)})
]
end{document}
This solves the problem only temporarily. If you nest elements, you'll run into similar problems because of the parameter text pattern matching. In general, it is safer to group arguments using {
...}
.
add a comment |
up vote
9
down vote
Your def
contains a very specific sequence defined as the parameter text:
% 1 2 3 4 5
deftwomate(<1>,<2>,<3>,<4>){ ... }
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └ comma ┘ │
% └─── bracket ───┘
This parameter text is matched exactly in order (almost like a first-come-first-served style) to extract the four arguments <1>
, <2>
, <3>
and <4>
. Here's how the elements are grabbed for twomate
with the above notation:
% 1 2 3 4 5
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └────── comma ────────┘ │
% └───────────────── bracket ──────────────────┘
It should be clear that the last bracket )
isn't properly captured for pwr
. The way around it is to hide pwr(.)
from twomate
:
documentclass{article}
usepackage{amsmath}
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),{-2epwr(2t)})
]
end{document}
This solves the problem only temporarily. If you nest elements, you'll run into similar problems because of the parameter text pattern matching. In general, it is safer to group arguments using {
...}
.
add a comment |
up vote
9
down vote
up vote
9
down vote
Your def
contains a very specific sequence defined as the parameter text:
% 1 2 3 4 5
deftwomate(<1>,<2>,<3>,<4>){ ... }
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └ comma ┘ │
% └─── bracket ───┘
This parameter text is matched exactly in order (almost like a first-come-first-served style) to extract the four arguments <1>
, <2>
, <3>
and <4>
. Here's how the elements are grabbed for twomate
with the above notation:
% 1 2 3 4 5
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └────── comma ────────┘ │
% └───────────────── bracket ──────────────────┘
It should be clear that the last bracket )
isn't properly captured for pwr
. The way around it is to hide pwr(.)
from twomate
:
documentclass{article}
usepackage{amsmath}
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),{-2epwr(2t)})
]
end{document}
This solves the problem only temporarily. If you nest elements, you'll run into similar problems because of the parameter text pattern matching. In general, it is safer to group arguments using {
...}
.
Your def
contains a very specific sequence defined as the parameter text:
% 1 2 3 4 5
deftwomate(<1>,<2>,<3>,<4>){ ... }
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └ comma ┘ │
% └─── bracket ───┘
This parameter text is matched exactly in order (almost like a first-come-first-served style) to extract the four arguments <1>
, <2>
, <3>
and <4>
. Here's how the elements are grabbed for twomate
with the above notation:
% 1 2 3 4 5
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
% ^ ^ ^ ^ ^
% │ │ │ │ │
% │ └────── comma ────────┘ │
% └───────────────── bracket ──────────────────┘
It should be clear that the last bracket )
isn't properly captured for pwr
. The way around it is to hide pwr(.)
from twomate
:
documentclass{article}
usepackage{amsmath}
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),{-2epwr(2t)})
]
end{document}
This solves the problem only temporarily. If you nest elements, you'll run into similar problems because of the parameter text pattern matching. In general, it is safer to group arguments using {
...}
.
edited yesterday
answered yesterday
Werner
429k589421618
429k589421618
add a comment |
add a comment |
up vote
5
down vote
TeX's delimited parameters parsing doesn't take nesting into account properly. So if you call twomate(3epwr(-3t), ...)
, the final )
for twomate
isn't found at the end of that line but at the end of pwr(-3t)
. The improperly formed call of pwr
then causes trouble.
To hide nested calls of your commands, put them into { ... }
groups (though this probably defeats the purpose):
documentclass{article}
usepackage{amsmath}
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}
begin{document}
[ twomate({3epwr(-3t)},{epwr(2t)},{-epwr(-3t)},{-2epwr(2t)}) ]
end{document}
By the way, don't use $$ ... $$
for display math environments but LaTeX's or amsmath
's variants like [ ... ]
.
add a comment |
up vote
5
down vote
TeX's delimited parameters parsing doesn't take nesting into account properly. So if you call twomate(3epwr(-3t), ...)
, the final )
for twomate
isn't found at the end of that line but at the end of pwr(-3t)
. The improperly formed call of pwr
then causes trouble.
To hide nested calls of your commands, put them into { ... }
groups (though this probably defeats the purpose):
documentclass{article}
usepackage{amsmath}
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}
begin{document}
[ twomate({3epwr(-3t)},{epwr(2t)},{-epwr(-3t)},{-2epwr(2t)}) ]
end{document}
By the way, don't use $$ ... $$
for display math environments but LaTeX's or amsmath
's variants like [ ... ]
.
add a comment |
up vote
5
down vote
up vote
5
down vote
TeX's delimited parameters parsing doesn't take nesting into account properly. So if you call twomate(3epwr(-3t), ...)
, the final )
for twomate
isn't found at the end of that line but at the end of pwr(-3t)
. The improperly formed call of pwr
then causes trouble.
To hide nested calls of your commands, put them into { ... }
groups (though this probably defeats the purpose):
documentclass{article}
usepackage{amsmath}
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}
begin{document}
[ twomate({3epwr(-3t)},{epwr(2t)},{-epwr(-3t)},{-2epwr(2t)}) ]
end{document}
By the way, don't use $$ ... $$
for display math environments but LaTeX's or amsmath
's variants like [ ... ]
.
TeX's delimited parameters parsing doesn't take nesting into account properly. So if you call twomate(3epwr(-3t), ...)
, the final )
for twomate
isn't found at the end of that line but at the end of pwr(-3t)
. The improperly formed call of pwr
then causes trouble.
To hide nested calls of your commands, put them into { ... }
groups (though this probably defeats the purpose):
documentclass{article}
usepackage{amsmath}
deftwomate(#1,#2,#3,#4){begin{pmatrix}#1\#3end{pmatrix}}
defpwr(#1){^{#1}}
deftwoclmn(#1,#2){begin{pmatrix}#1\#2end{pmatrix}}
begin{document}
[ twomate({3epwr(-3t)},{epwr(2t)},{-epwr(-3t)},{-2epwr(2t)}) ]
end{document}
By the way, don't use $$ ... $$
for display math environments but LaTeX's or amsmath
's variants like [ ... ]
.
edited yesterday
answered yesterday
siracusa
4,31911127
4,31911127
add a comment |
add a comment |
up vote
2
down vote
original answer
Here is a way to define macros fetching their arguments like "functions" in many programming language.
It is lifted from the xintexpr
code.
I had a bit forgotten the details, and left the code comments of XINT_isbalanced_a
for those interested.
now that things come back more to my memory: of course comma separation of arguments will cause further issues. The xintexpr parser does not use at all this mechanism for implementing comma separated arguments of "functions". The mechanism as here is applied only for things such as seq(<expression>, x=1..10)
where the <expression>
if fetched as delimited by a comma, and then the balancing test is applied to it in case it was for example seq(myfunction(x,x^2),x=1..10)
where the first comma would have been intially mistakendly taken as delimiter, but then the code realizes it is not balanced so it goes further.
thus, now that I think about it, nesting here would need checking the arguments picked up by comma delimited macros are balanced with respect to parentheses. I have not applied it yet, as the poor man approach here is still very low-weight and is enough for the OP use cases
See below how applyfunction
is to be used.
(but as I explained in paragraphs above this is not provided as a nestable thing, only "functions" with 1 argument can be nested inside others; perhaps I will edit later to provide fuller solution).
Thus this is a no-package solution.
documentclass{article}
% copy over some utility code from package xintexpr
catcode`_ 11
makeatletter
letxint_c_monem@ne
letxint_c_z@
letxint_c_i@ne
longdefxint_bye #1xint_bye {}%
makeatother
% % end{macrocode}
% subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
% lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
% it, to @ne if opening ( had no closing ) matching it, to z@ if expression
% was balanced.|
% begin{macrocode}
% use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
defXINT_isbalanced_b #1)#2%
{xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
% end{macrocode}
% lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
% begin{macrocode}
defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
% end{macrocode}
% lverb|#2 was xint_bye, was there a ) in original #1?|
% begin{macrocode}
defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
{xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
% end{macrocode}
% lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
% begin{macrocode}
defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
% end{macrocode}
% lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
% we see a ). If we do, we then loop until no ( nor ) is to be found.|
% begin{macrocode}
defXINT_isbalanced_d #1)#2%
{xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
% end{macrocode}
% lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
% begin{macrocode}
defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%
% Define a utility to apply a "function", comma separated arguments
defapplyfunction #1(#2)%
{%
ifcaseXINT_isbalanced_a relax #1#2(xint_bye)xint_bye
expandafterapplyfunction_doit
orexpandafterapplyfunction_again
elseexpandafterwe_are_doomed
fi {#1#2}%
}%
defapplyfunction_doit #1{#1,}
defapplyfunction_again #1{applyfunction {#1)}(}
catcode`_ 8
usepackage{amsmath}
makeatletter
% function wrappers
deftwomate{applyfunctiontwomate@csv}
defpwr{applyfunctionpwr@csv}
deftwoclmn{applyfunctiontwoclmn@csv}
% define macros with comma delimited arguments
deftwomate@csv#1,#2,#3,#4,{begin{pmatrix}#1\#3end{pmatrix}}
defpwr@csv#1,{^{#1}}
deftwoclmn@csv#1,#2,{begin{pmatrix}#1\#2end{pmatrix}}
%
makeatother
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
]
[
twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
+ frac25 t epwr(2t))
]
end{document}
updated answer
Original code allowed only nesting of "function" with one-argument inside other "functions".
Updated code makes more general nesting possible, we will test it with this input
foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))
and it works.
Notice that this code works only by expansion.
Code:
documentclass{article}
usepackage{amsmath}
% copy over some utility code from package xintexpr
catcode`_ 11
makeatletter
letxint_c_monem@ne
letxint_c_z@
letxint_c_i@ne
longdefxint_bye #1xint_bye {}%
makeatother
% NOTICE THAT ALL MACROS NEXT SHOULD BE MADE `long` ARGUABLY
% IT WAS NOT NEEDED IN XINTEXPR CONTEXT
% % end{macrocode}
% subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
% lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
% it, to @ne if opening ( had no closing ) matching it, to z@ if expression
% was balanced.|
% begin{macrocode}
% use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
defXINT_isbalanced_b #1)#2%
{xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
% end{macrocode}
% lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
% begin{macrocode}
defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
% end{macrocode}
% lverb|#2 was xint_bye, was there a ) in original #1?|
% begin{macrocode}
defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
{xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
% end{macrocode}
% lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
% begin{macrocode}
defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
% end{macrocode}
% lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
% we see a ). If we do, we then loop until no ( nor ) is to be found.|
% begin{macrocode}
defXINT_isbalanced_d #1)#2%
{xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
% end{macrocode}
% lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
% begin{macrocode}
defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%
% New utility (expandable)
longdefapplyfunction #1#2)%
{%
ifcaseXINT_isbalanced_a relax #1#2)(xint_bye)xint_bye
expandafterapplyfunction_b
orexpandafterapplyfunction_again
elseexpandafterwe_are_doomed
fi {#1#2}%
}%
longdefapplyfunction_again #1{applyfunction {#1)}}%
longdefmy_bbye #1my_bbye {}%
longdefapplyfunction_b #1{applyfunction_c #1,my_bbye,}%
longdefapplyfunction_c #1({applyfunction_d #1{}{}}%
% we will take care of brace removal another day
longdefapplyfunction_d #1#2#3#4,%
{%
ifcaseXINT_isbalanced_a relax #3#4(xint_bye)xint_bye
expandafterapplyfunction_e
orexpandafterapplyfunction_d_again
elseexpandafterwe_are_doomed
fi #1{#2}{#3}{#4}%
}%
longdefapplyfunction_d_again #1#2#3#4%
{%
applyfunction_d #1{#2}{#3#4,}%
}%
longdefapplyfunction_e #1#2#3#4%
{%
my_bbye#4applyfunction_finishmy_bbye
applyfunction_g #1{#2}{#3#4}%
}%
longdefapplyfunction_g #1#2#3{applyfunction_d #1{#2{#3}}{}}%
longdefapplyfunction_finishmy_bbyeapplyfunction_g #1#2#3{#1#2}%
catcode`_ 8
%% USAGE
% "functions" to be used as foo(a,b,c,...)
% Syntax: applyfunctionnondelimitedmacro
% Number of arguments is determined dynamically (at most 9)
makeatletter
newcommandtwomate{applyfunctiontwomate@macro}
newcommandpwr{applyfunctionpwr@macro}
newcommandtwoclmn{applyfunctiontwoclmn@macro}
% define here the **non-delimited** auxiliary macros
newcommandtwomate@macro[4]{begin{pmatrix}#1\#3end{pmatrix}}
newcommandpwr@macro[1]{^{#1}}
newcommandtwoclmn@macro[2]{begin{pmatrix}#1\#2end{pmatrix}}
makeatother
%% TESTING NESTING
makeatletter
newcommandfoo{applyfunctionfoo@macro}
newcommandfoo@macro[4]{left[#1+#2+#3+#4right]}
letBarrelax
newcommandBar{applyfunctionBar@macro}
newcommandBar@macro[3]{left(#1*#2*#3right)}
makeatother
delimiterfactor1001
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
]
[
twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
+ frac25 t epwr(2t))
]
[foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))]
end{document}
add a comment |
up vote
2
down vote
original answer
Here is a way to define macros fetching their arguments like "functions" in many programming language.
It is lifted from the xintexpr
code.
I had a bit forgotten the details, and left the code comments of XINT_isbalanced_a
for those interested.
now that things come back more to my memory: of course comma separation of arguments will cause further issues. The xintexpr parser does not use at all this mechanism for implementing comma separated arguments of "functions". The mechanism as here is applied only for things such as seq(<expression>, x=1..10)
where the <expression>
if fetched as delimited by a comma, and then the balancing test is applied to it in case it was for example seq(myfunction(x,x^2),x=1..10)
where the first comma would have been intially mistakendly taken as delimiter, but then the code realizes it is not balanced so it goes further.
thus, now that I think about it, nesting here would need checking the arguments picked up by comma delimited macros are balanced with respect to parentheses. I have not applied it yet, as the poor man approach here is still very low-weight and is enough for the OP use cases
See below how applyfunction
is to be used.
(but as I explained in paragraphs above this is not provided as a nestable thing, only "functions" with 1 argument can be nested inside others; perhaps I will edit later to provide fuller solution).
Thus this is a no-package solution.
documentclass{article}
% copy over some utility code from package xintexpr
catcode`_ 11
makeatletter
letxint_c_monem@ne
letxint_c_z@
letxint_c_i@ne
longdefxint_bye #1xint_bye {}%
makeatother
% % end{macrocode}
% subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
% lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
% it, to @ne if opening ( had no closing ) matching it, to z@ if expression
% was balanced.|
% begin{macrocode}
% use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
defXINT_isbalanced_b #1)#2%
{xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
% end{macrocode}
% lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
% begin{macrocode}
defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
% end{macrocode}
% lverb|#2 was xint_bye, was there a ) in original #1?|
% begin{macrocode}
defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
{xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
% end{macrocode}
% lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
% begin{macrocode}
defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
% end{macrocode}
% lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
% we see a ). If we do, we then loop until no ( nor ) is to be found.|
% begin{macrocode}
defXINT_isbalanced_d #1)#2%
{xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
% end{macrocode}
% lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
% begin{macrocode}
defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%
% Define a utility to apply a "function", comma separated arguments
defapplyfunction #1(#2)%
{%
ifcaseXINT_isbalanced_a relax #1#2(xint_bye)xint_bye
expandafterapplyfunction_doit
orexpandafterapplyfunction_again
elseexpandafterwe_are_doomed
fi {#1#2}%
}%
defapplyfunction_doit #1{#1,}
defapplyfunction_again #1{applyfunction {#1)}(}
catcode`_ 8
usepackage{amsmath}
makeatletter
% function wrappers
deftwomate{applyfunctiontwomate@csv}
defpwr{applyfunctionpwr@csv}
deftwoclmn{applyfunctiontwoclmn@csv}
% define macros with comma delimited arguments
deftwomate@csv#1,#2,#3,#4,{begin{pmatrix}#1\#3end{pmatrix}}
defpwr@csv#1,{^{#1}}
deftwoclmn@csv#1,#2,{begin{pmatrix}#1\#2end{pmatrix}}
%
makeatother
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
]
[
twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
+ frac25 t epwr(2t))
]
end{document}
updated answer
Original code allowed only nesting of "function" with one-argument inside other "functions".
Updated code makes more general nesting possible, we will test it with this input
foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))
and it works.
Notice that this code works only by expansion.
Code:
documentclass{article}
usepackage{amsmath}
% copy over some utility code from package xintexpr
catcode`_ 11
makeatletter
letxint_c_monem@ne
letxint_c_z@
letxint_c_i@ne
longdefxint_bye #1xint_bye {}%
makeatother
% NOTICE THAT ALL MACROS NEXT SHOULD BE MADE `long` ARGUABLY
% IT WAS NOT NEEDED IN XINTEXPR CONTEXT
% % end{macrocode}
% subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
% lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
% it, to @ne if opening ( had no closing ) matching it, to z@ if expression
% was balanced.|
% begin{macrocode}
% use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
defXINT_isbalanced_b #1)#2%
{xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
% end{macrocode}
% lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
% begin{macrocode}
defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
% end{macrocode}
% lverb|#2 was xint_bye, was there a ) in original #1?|
% begin{macrocode}
defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
{xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
% end{macrocode}
% lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
% begin{macrocode}
defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
% end{macrocode}
% lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
% we see a ). If we do, we then loop until no ( nor ) is to be found.|
% begin{macrocode}
defXINT_isbalanced_d #1)#2%
{xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
% end{macrocode}
% lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
% begin{macrocode}
defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%
% New utility (expandable)
longdefapplyfunction #1#2)%
{%
ifcaseXINT_isbalanced_a relax #1#2)(xint_bye)xint_bye
expandafterapplyfunction_b
orexpandafterapplyfunction_again
elseexpandafterwe_are_doomed
fi {#1#2}%
}%
longdefapplyfunction_again #1{applyfunction {#1)}}%
longdefmy_bbye #1my_bbye {}%
longdefapplyfunction_b #1{applyfunction_c #1,my_bbye,}%
longdefapplyfunction_c #1({applyfunction_d #1{}{}}%
% we will take care of brace removal another day
longdefapplyfunction_d #1#2#3#4,%
{%
ifcaseXINT_isbalanced_a relax #3#4(xint_bye)xint_bye
expandafterapplyfunction_e
orexpandafterapplyfunction_d_again
elseexpandafterwe_are_doomed
fi #1{#2}{#3}{#4}%
}%
longdefapplyfunction_d_again #1#2#3#4%
{%
applyfunction_d #1{#2}{#3#4,}%
}%
longdefapplyfunction_e #1#2#3#4%
{%
my_bbye#4applyfunction_finishmy_bbye
applyfunction_g #1{#2}{#3#4}%
}%
longdefapplyfunction_g #1#2#3{applyfunction_d #1{#2{#3}}{}}%
longdefapplyfunction_finishmy_bbyeapplyfunction_g #1#2#3{#1#2}%
catcode`_ 8
%% USAGE
% "functions" to be used as foo(a,b,c,...)
% Syntax: applyfunctionnondelimitedmacro
% Number of arguments is determined dynamically (at most 9)
makeatletter
newcommandtwomate{applyfunctiontwomate@macro}
newcommandpwr{applyfunctionpwr@macro}
newcommandtwoclmn{applyfunctiontwoclmn@macro}
% define here the **non-delimited** auxiliary macros
newcommandtwomate@macro[4]{begin{pmatrix}#1\#3end{pmatrix}}
newcommandpwr@macro[1]{^{#1}}
newcommandtwoclmn@macro[2]{begin{pmatrix}#1\#2end{pmatrix}}
makeatother
%% TESTING NESTING
makeatletter
newcommandfoo{applyfunctionfoo@macro}
newcommandfoo@macro[4]{left[#1+#2+#3+#4right]}
letBarrelax
newcommandBar{applyfunctionBar@macro}
newcommandBar@macro[3]{left(#1*#2*#3right)}
makeatother
delimiterfactor1001
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
]
[
twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
+ frac25 t epwr(2t))
]
[foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))]
end{document}
add a comment |
up vote
2
down vote
up vote
2
down vote
original answer
Here is a way to define macros fetching their arguments like "functions" in many programming language.
It is lifted from the xintexpr
code.
I had a bit forgotten the details, and left the code comments of XINT_isbalanced_a
for those interested.
now that things come back more to my memory: of course comma separation of arguments will cause further issues. The xintexpr parser does not use at all this mechanism for implementing comma separated arguments of "functions". The mechanism as here is applied only for things such as seq(<expression>, x=1..10)
where the <expression>
if fetched as delimited by a comma, and then the balancing test is applied to it in case it was for example seq(myfunction(x,x^2),x=1..10)
where the first comma would have been intially mistakendly taken as delimiter, but then the code realizes it is not balanced so it goes further.
thus, now that I think about it, nesting here would need checking the arguments picked up by comma delimited macros are balanced with respect to parentheses. I have not applied it yet, as the poor man approach here is still very low-weight and is enough for the OP use cases
See below how applyfunction
is to be used.
(but as I explained in paragraphs above this is not provided as a nestable thing, only "functions" with 1 argument can be nested inside others; perhaps I will edit later to provide fuller solution).
Thus this is a no-package solution.
documentclass{article}
% copy over some utility code from package xintexpr
catcode`_ 11
makeatletter
letxint_c_monem@ne
letxint_c_z@
letxint_c_i@ne
longdefxint_bye #1xint_bye {}%
makeatother
% % end{macrocode}
% subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
% lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
% it, to @ne if opening ( had no closing ) matching it, to z@ if expression
% was balanced.|
% begin{macrocode}
% use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
defXINT_isbalanced_b #1)#2%
{xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
% end{macrocode}
% lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
% begin{macrocode}
defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
% end{macrocode}
% lverb|#2 was xint_bye, was there a ) in original #1?|
% begin{macrocode}
defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
{xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
% end{macrocode}
% lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
% begin{macrocode}
defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
% end{macrocode}
% lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
% we see a ). If we do, we then loop until no ( nor ) is to be found.|
% begin{macrocode}
defXINT_isbalanced_d #1)#2%
{xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
% end{macrocode}
% lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
% begin{macrocode}
defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%
% Define a utility to apply a "function", comma separated arguments
defapplyfunction #1(#2)%
{%
ifcaseXINT_isbalanced_a relax #1#2(xint_bye)xint_bye
expandafterapplyfunction_doit
orexpandafterapplyfunction_again
elseexpandafterwe_are_doomed
fi {#1#2}%
}%
defapplyfunction_doit #1{#1,}
defapplyfunction_again #1{applyfunction {#1)}(}
catcode`_ 8
usepackage{amsmath}
makeatletter
% function wrappers
deftwomate{applyfunctiontwomate@csv}
defpwr{applyfunctionpwr@csv}
deftwoclmn{applyfunctiontwoclmn@csv}
% define macros with comma delimited arguments
deftwomate@csv#1,#2,#3,#4,{begin{pmatrix}#1\#3end{pmatrix}}
defpwr@csv#1,{^{#1}}
deftwoclmn@csv#1,#2,{begin{pmatrix}#1\#2end{pmatrix}}
%
makeatother
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
]
[
twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
+ frac25 t epwr(2t))
]
end{document}
updated answer
Original code allowed only nesting of "function" with one-argument inside other "functions".
Updated code makes more general nesting possible, we will test it with this input
foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))
and it works.
Notice that this code works only by expansion.
Code:
documentclass{article}
usepackage{amsmath}
% copy over some utility code from package xintexpr
catcode`_ 11
makeatletter
letxint_c_monem@ne
letxint_c_z@
letxint_c_i@ne
longdefxint_bye #1xint_bye {}%
makeatother
% NOTICE THAT ALL MACROS NEXT SHOULD BE MADE `long` ARGUABLY
% IT WAS NOT NEEDED IN XINTEXPR CONTEXT
% % end{macrocode}
% subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
% lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
% it, to @ne if opening ( had no closing ) matching it, to z@ if expression
% was balanced.|
% begin{macrocode}
% use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
defXINT_isbalanced_b #1)#2%
{xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
% end{macrocode}
% lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
% begin{macrocode}
defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
% end{macrocode}
% lverb|#2 was xint_bye, was there a ) in original #1?|
% begin{macrocode}
defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
{xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
% end{macrocode}
% lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
% begin{macrocode}
defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
% end{macrocode}
% lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
% we see a ). If we do, we then loop until no ( nor ) is to be found.|
% begin{macrocode}
defXINT_isbalanced_d #1)#2%
{xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
% end{macrocode}
% lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
% begin{macrocode}
defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%
% New utility (expandable)
longdefapplyfunction #1#2)%
{%
ifcaseXINT_isbalanced_a relax #1#2)(xint_bye)xint_bye
expandafterapplyfunction_b
orexpandafterapplyfunction_again
elseexpandafterwe_are_doomed
fi {#1#2}%
}%
longdefapplyfunction_again #1{applyfunction {#1)}}%
longdefmy_bbye #1my_bbye {}%
longdefapplyfunction_b #1{applyfunction_c #1,my_bbye,}%
longdefapplyfunction_c #1({applyfunction_d #1{}{}}%
% we will take care of brace removal another day
longdefapplyfunction_d #1#2#3#4,%
{%
ifcaseXINT_isbalanced_a relax #3#4(xint_bye)xint_bye
expandafterapplyfunction_e
orexpandafterapplyfunction_d_again
elseexpandafterwe_are_doomed
fi #1{#2}{#3}{#4}%
}%
longdefapplyfunction_d_again #1#2#3#4%
{%
applyfunction_d #1{#2}{#3#4,}%
}%
longdefapplyfunction_e #1#2#3#4%
{%
my_bbye#4applyfunction_finishmy_bbye
applyfunction_g #1{#2}{#3#4}%
}%
longdefapplyfunction_g #1#2#3{applyfunction_d #1{#2{#3}}{}}%
longdefapplyfunction_finishmy_bbyeapplyfunction_g #1#2#3{#1#2}%
catcode`_ 8
%% USAGE
% "functions" to be used as foo(a,b,c,...)
% Syntax: applyfunctionnondelimitedmacro
% Number of arguments is determined dynamically (at most 9)
makeatletter
newcommandtwomate{applyfunctiontwomate@macro}
newcommandpwr{applyfunctionpwr@macro}
newcommandtwoclmn{applyfunctiontwoclmn@macro}
% define here the **non-delimited** auxiliary macros
newcommandtwomate@macro[4]{begin{pmatrix}#1\#3end{pmatrix}}
newcommandpwr@macro[1]{^{#1}}
newcommandtwoclmn@macro[2]{begin{pmatrix}#1\#2end{pmatrix}}
makeatother
%% TESTING NESTING
makeatletter
newcommandfoo{applyfunctionfoo@macro}
newcommandfoo@macro[4]{left[#1+#2+#3+#4right]}
letBarrelax
newcommandBar{applyfunctionBar@macro}
newcommandBar@macro[3]{left(#1*#2*#3right)}
makeatother
delimiterfactor1001
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
]
[
twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
+ frac25 t epwr(2t))
]
[foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))]
end{document}
original answer
Here is a way to define macros fetching their arguments like "functions" in many programming language.
It is lifted from the xintexpr
code.
I had a bit forgotten the details, and left the code comments of XINT_isbalanced_a
for those interested.
now that things come back more to my memory: of course comma separation of arguments will cause further issues. The xintexpr parser does not use at all this mechanism for implementing comma separated arguments of "functions". The mechanism as here is applied only for things such as seq(<expression>, x=1..10)
where the <expression>
if fetched as delimited by a comma, and then the balancing test is applied to it in case it was for example seq(myfunction(x,x^2),x=1..10)
where the first comma would have been intially mistakendly taken as delimiter, but then the code realizes it is not balanced so it goes further.
thus, now that I think about it, nesting here would need checking the arguments picked up by comma delimited macros are balanced with respect to parentheses. I have not applied it yet, as the poor man approach here is still very low-weight and is enough for the OP use cases
See below how applyfunction
is to be used.
(but as I explained in paragraphs above this is not provided as a nestable thing, only "functions" with 1 argument can be nested inside others; perhaps I will edit later to provide fuller solution).
Thus this is a no-package solution.
documentclass{article}
% copy over some utility code from package xintexpr
catcode`_ 11
makeatletter
letxint_c_monem@ne
letxint_c_z@
letxint_c_i@ne
longdefxint_bye #1xint_bye {}%
makeatother
% % end{macrocode}
% subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
% lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
% it, to @ne if opening ( had no closing ) matching it, to z@ if expression
% was balanced.|
% begin{macrocode}
% use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
defXINT_isbalanced_b #1)#2%
{xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
% end{macrocode}
% lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
% begin{macrocode}
defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
% end{macrocode}
% lverb|#2 was xint_bye, was there a ) in original #1?|
% begin{macrocode}
defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
{xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
% end{macrocode}
% lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
% begin{macrocode}
defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
% end{macrocode}
% lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
% we see a ). If we do, we then loop until no ( nor ) is to be found.|
% begin{macrocode}
defXINT_isbalanced_d #1)#2%
{xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
% end{macrocode}
% lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
% begin{macrocode}
defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%
% Define a utility to apply a "function", comma separated arguments
defapplyfunction #1(#2)%
{%
ifcaseXINT_isbalanced_a relax #1#2(xint_bye)xint_bye
expandafterapplyfunction_doit
orexpandafterapplyfunction_again
elseexpandafterwe_are_doomed
fi {#1#2}%
}%
defapplyfunction_doit #1{#1,}
defapplyfunction_again #1{applyfunction {#1)}(}
catcode`_ 8
usepackage{amsmath}
makeatletter
% function wrappers
deftwomate{applyfunctiontwomate@csv}
defpwr{applyfunctionpwr@csv}
deftwoclmn{applyfunctiontwoclmn@csv}
% define macros with comma delimited arguments
deftwomate@csv#1,#2,#3,#4,{begin{pmatrix}#1\#3end{pmatrix}}
defpwr@csv#1,{^{#1}}
deftwoclmn@csv#1,#2,{begin{pmatrix}#1\#2end{pmatrix}}
%
makeatother
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
]
[
twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
+ frac25 t epwr(2t))
]
end{document}
updated answer
Original code allowed only nesting of "function" with one-argument inside other "functions".
Updated code makes more general nesting possible, we will test it with this input
foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))
and it works.
Notice that this code works only by expansion.
Code:
documentclass{article}
usepackage{amsmath}
% copy over some utility code from package xintexpr
catcode`_ 11
makeatletter
letxint_c_monem@ne
letxint_c_z@
letxint_c_i@ne
longdefxint_bye #1xint_bye {}%
makeatother
% NOTICE THAT ALL MACROS NEXT SHOULD BE MADE `long` ARGUABLY
% IT WAS NOT NEEDED IN XINTEXPR CONTEXT
% % end{macrocode}
% subsubsection{csh{XINT_isbalanced_a} for cshnolabel{XINT_expr_onliteral_seq_a}}
% lverb|Expands to xint_c_mone in case a closing ) had no opening ( matching
% it, to @ne if opening ( had no closing ) matching it, to z@ if expression
% was balanced.|
% begin{macrocode}
% use as XINT_isbalanced_a relax #1(xint_bye)xint_bye
defXINT_isbalanced_a #1({XINT_isbalanced_b #1)xint_bye }%
defXINT_isbalanced_b #1)#2%
{xint_bye #2XINT_isbalanced_cxint_byeXINT_isbalanced_error }%
% end{macrocode}
% lverb|if #2 is not xint_bye, a ) was found, but there was no (. Hence error -> -1|
% begin{macrocode}
defXINT_isbalanced_error #1)xint_bye {xint_c_mone}%
% end{macrocode}
% lverb|#2 was xint_bye, was there a ) in original #1?|
% begin{macrocode}
defXINT_isbalanced_cxint_byeXINT_isbalanced_error #1%
{xint_bye #1XINT_isbalanced_yesxint_byeXINT_isbalanced_d #1}%
% end{macrocode}
% lverb|#1 is xint_bye, there was never ( nor ) in original #1, hence OK.|
% begin{macrocode}
defXINT_isbalanced_yesxint_byeXINT_isbalanced_dxint_bye )xint_bye {xint_c_ }%
% end{macrocode}
% lverb|#1 is not xint_bye, there was indeed a ( in original #1. We check if
% we see a ). If we do, we then loop until no ( nor ) is to be found.|
% begin{macrocode}
defXINT_isbalanced_d #1)#2%
{xint_bye #2XINT_isbalanced_noxint_byeXINT_isbalanced_a #1#2}%
% end{macrocode}
% lverb|#2 was xint_bye, we did not find a closing ) in original #1. Error.|
% begin{macrocode}
defXINT_isbalanced_noxint_bye #1xint_byexint_bye {xint_c_i }%
% New utility (expandable)
longdefapplyfunction #1#2)%
{%
ifcaseXINT_isbalanced_a relax #1#2)(xint_bye)xint_bye
expandafterapplyfunction_b
orexpandafterapplyfunction_again
elseexpandafterwe_are_doomed
fi {#1#2}%
}%
longdefapplyfunction_again #1{applyfunction {#1)}}%
longdefmy_bbye #1my_bbye {}%
longdefapplyfunction_b #1{applyfunction_c #1,my_bbye,}%
longdefapplyfunction_c #1({applyfunction_d #1{}{}}%
% we will take care of brace removal another day
longdefapplyfunction_d #1#2#3#4,%
{%
ifcaseXINT_isbalanced_a relax #3#4(xint_bye)xint_bye
expandafterapplyfunction_e
orexpandafterapplyfunction_d_again
elseexpandafterwe_are_doomed
fi #1{#2}{#3}{#4}%
}%
longdefapplyfunction_d_again #1#2#3#4%
{%
applyfunction_d #1{#2}{#3#4,}%
}%
longdefapplyfunction_e #1#2#3#4%
{%
my_bbye#4applyfunction_finishmy_bbye
applyfunction_g #1{#2}{#3#4}%
}%
longdefapplyfunction_g #1#2#3{applyfunction_d #1{#2{#3}}{}}%
longdefapplyfunction_finishmy_bbyeapplyfunction_g #1#2#3{#1#2}%
catcode`_ 8
%% USAGE
% "functions" to be used as foo(a,b,c,...)
% Syntax: applyfunctionnondelimitedmacro
% Number of arguments is determined dynamically (at most 9)
makeatletter
newcommandtwomate{applyfunctiontwomate@macro}
newcommandpwr{applyfunctionpwr@macro}
newcommandtwoclmn{applyfunctiontwoclmn@macro}
% define here the **non-delimited** auxiliary macros
newcommandtwomate@macro[4]{begin{pmatrix}#1\#3end{pmatrix}}
newcommandpwr@macro[1]{^{#1}}
newcommandtwoclmn@macro[2]{begin{pmatrix}#1\#2end{pmatrix}}
makeatother
%% TESTING NESTING
makeatletter
newcommandfoo{applyfunctionfoo@macro}
newcommandfoo@macro[4]{left[#1+#2+#3+#4right]}
letBarrelax
newcommandBar{applyfunctionBar@macro}
newcommandBar@macro[3]{left(#1*#2*#3right)}
makeatother
delimiterfactor1001
begin{document}
[
twomate(3epwr(-3t),epwr(2t),-epwr(-3t),-2epwr(2t))
]
[
twoclmn(frac{6}{25}epwr(2t)-frac15tepwr(2t),-frac{2}{25}epwr(2t)
+ frac25 t epwr(2t))
]
[foo(Bar(3,5,7),Bar(9,foo(a,Bar(W,X,Y),c,d),13),Bar(15,17,19),Bar(21,23,25))]
end{document}
edited 8 hours ago
answered 15 hours ago
jfbu
43.9k65142
43.9k65142
add a comment |
add a comment |
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.
Hossmeister is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Since you're using LaTeX, please consider using
[ ... ]
instead of$$ ... $$
, as the latter causes some inconsistencies.– AJFarmar
11 hours ago