Defining a command part by part
Let's say we have a command foo
with 1 argument. Can we produce a command setfoo{aaa}{<some thing>}
which redefines foo
to:
if an argument of foo
is equal to 'aaa', do ; otherwise do what foo
was supposed to do previously? I would also like to use setfoo
many times, so
setfoo{a}{part1}
setfoo{b}{part2}
setfoo{c}{part3}
foo{a} foo{b} foo{c}
would produce
part1 part2 part3
I've tried the following:
documentclass{article}
usepackage{ifthen}
newcommand{foo}[1]{}
%letoldfoofoo%
newcommand{setfoo}[2]{
letoldfoofoo %<- to save current foo
renewcommand{foo}[1]{
ifthenelse{equal{##1}{#1}}{#2}{oldfoo{##1}}%
}
}
begin{document}
setfoo{a}{part1}
setfoo{b}{part2}
%setfoo{c}{part3}
foo{a} foo{a} foo{c}
end{document}
But it works only if there are <=2 uses of setfoo
. Otherwise, compilation doesn't stop for a few minutes so I guess something is not working. How can this be fixed? Thanks in advance.
macros conditionals
add a comment |
Let's say we have a command foo
with 1 argument. Can we produce a command setfoo{aaa}{<some thing>}
which redefines foo
to:
if an argument of foo
is equal to 'aaa', do ; otherwise do what foo
was supposed to do previously? I would also like to use setfoo
many times, so
setfoo{a}{part1}
setfoo{b}{part2}
setfoo{c}{part3}
foo{a} foo{b} foo{c}
would produce
part1 part2 part3
I've tried the following:
documentclass{article}
usepackage{ifthen}
newcommand{foo}[1]{}
%letoldfoofoo%
newcommand{setfoo}[2]{
letoldfoofoo %<- to save current foo
renewcommand{foo}[1]{
ifthenelse{equal{##1}{#1}}{#2}{oldfoo{##1}}%
}
}
begin{document}
setfoo{a}{part1}
setfoo{b}{part2}
%setfoo{c}{part3}
foo{a} foo{a} foo{c}
end{document}
But it works only if there are <=2 uses of setfoo
. Otherwise, compilation doesn't stop for a few minutes so I guess something is not working. How can this be fixed? Thanks in advance.
macros conditionals
1
Welcome to TeX.SE!
– Kurt
Jan 22 at 23:58
add a comment |
Let's say we have a command foo
with 1 argument. Can we produce a command setfoo{aaa}{<some thing>}
which redefines foo
to:
if an argument of foo
is equal to 'aaa', do ; otherwise do what foo
was supposed to do previously? I would also like to use setfoo
many times, so
setfoo{a}{part1}
setfoo{b}{part2}
setfoo{c}{part3}
foo{a} foo{b} foo{c}
would produce
part1 part2 part3
I've tried the following:
documentclass{article}
usepackage{ifthen}
newcommand{foo}[1]{}
%letoldfoofoo%
newcommand{setfoo}[2]{
letoldfoofoo %<- to save current foo
renewcommand{foo}[1]{
ifthenelse{equal{##1}{#1}}{#2}{oldfoo{##1}}%
}
}
begin{document}
setfoo{a}{part1}
setfoo{b}{part2}
%setfoo{c}{part3}
foo{a} foo{a} foo{c}
end{document}
But it works only if there are <=2 uses of setfoo
. Otherwise, compilation doesn't stop for a few minutes so I guess something is not working. How can this be fixed? Thanks in advance.
macros conditionals
Let's say we have a command foo
with 1 argument. Can we produce a command setfoo{aaa}{<some thing>}
which redefines foo
to:
if an argument of foo
is equal to 'aaa', do ; otherwise do what foo
was supposed to do previously? I would also like to use setfoo
many times, so
setfoo{a}{part1}
setfoo{b}{part2}
setfoo{c}{part3}
foo{a} foo{b} foo{c}
would produce
part1 part2 part3
I've tried the following:
documentclass{article}
usepackage{ifthen}
newcommand{foo}[1]{}
%letoldfoofoo%
newcommand{setfoo}[2]{
letoldfoofoo %<- to save current foo
renewcommand{foo}[1]{
ifthenelse{equal{##1}{#1}}{#2}{oldfoo{##1}}%
}
}
begin{document}
setfoo{a}{part1}
setfoo{b}{part2}
%setfoo{c}{part3}
foo{a} foo{a} foo{c}
end{document}
But it works only if there are <=2 uses of setfoo
. Otherwise, compilation doesn't stop for a few minutes so I guess something is not working. How can this be fixed? Thanks in advance.
macros conditionals
macros conditionals
asked Jan 22 at 23:42
Tomasz23Tomasz23
506
506
1
Welcome to TeX.SE!
– Kurt
Jan 22 at 23:58
add a comment |
1
Welcome to TeX.SE!
– Kurt
Jan 22 at 23:58
1
1
Welcome to TeX.SE!
– Kurt
Jan 22 at 23:58
Welcome to TeX.SE!
– Kurt
Jan 22 at 23:58
add a comment |
2 Answers
2
active
oldest
votes
This is a job for csname
:
newcommand{setfoo}[2]{%
expandafternewcommandcsname tomasz@#1endcsname{#2}%
}
newcommand{foo}[1]{csname tomasz@#1endcsname}
You might use a check in foo
that the command is actually defined:
makeatletter
newcommand{foo}[1]{%
ifcsname tomasz@#1endcsname
expandafter@firstoftwo
else
expandafter@secondoftwo
fi
{csname tomasz@#1endcsname}%
{BUMMER!}%
}
makeatother
add a comment |
In your special case, where foo
is always to process a single undelimited non-optional argument, you can probably apply some expansion trickery for "flushing" the tokens that form the current definition of foo
into the new definition of foo
—one of the expansion-tricks is (ab)using romannumeral
for triggering expansion until LaTeX has found the number 0. romannumeral
's underlying conversion-routine does "swallow" non-positive numbers while silently not delivering any token at all:
documentclass{article}
usepackage{ifthen}
newcommandPassFirstToSecond[2]{#2{#1}}%
newcommand{foo}[1]{There is no setting for value #1.}
newcommand{setfoo}[2]{%
expandafterPassFirstToSecond
expandafter{%
romannumeralexpandafterPassFirstToSecondexpandafter{foo{##1}}%
{0 ifthenelse{equal{##1}{#1}}{#2}}%
}{renewcommand{foo}[1]}%
}
parindent=0ex
parskip=bigskipamount
begin{document}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{a}{part1}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{b}{part2}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{c}{part3}
texttt{stringfoospace currently is defined as:\ meaningfoo}
hrulefill
Some testing:
verb|foo{a}| yields: foo{a}
verb|foo{b}| yields: foo{b}
verb|foo{c}| yields: foo{c}
verb|foo{y}| yields: foo{y}
end{document}
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f471399%2fdefining-a-command-part-by-part%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
This is a job for csname
:
newcommand{setfoo}[2]{%
expandafternewcommandcsname tomasz@#1endcsname{#2}%
}
newcommand{foo}[1]{csname tomasz@#1endcsname}
You might use a check in foo
that the command is actually defined:
makeatletter
newcommand{foo}[1]{%
ifcsname tomasz@#1endcsname
expandafter@firstoftwo
else
expandafter@secondoftwo
fi
{csname tomasz@#1endcsname}%
{BUMMER!}%
}
makeatother
add a comment |
This is a job for csname
:
newcommand{setfoo}[2]{%
expandafternewcommandcsname tomasz@#1endcsname{#2}%
}
newcommand{foo}[1]{csname tomasz@#1endcsname}
You might use a check in foo
that the command is actually defined:
makeatletter
newcommand{foo}[1]{%
ifcsname tomasz@#1endcsname
expandafter@firstoftwo
else
expandafter@secondoftwo
fi
{csname tomasz@#1endcsname}%
{BUMMER!}%
}
makeatother
add a comment |
This is a job for csname
:
newcommand{setfoo}[2]{%
expandafternewcommandcsname tomasz@#1endcsname{#2}%
}
newcommand{foo}[1]{csname tomasz@#1endcsname}
You might use a check in foo
that the command is actually defined:
makeatletter
newcommand{foo}[1]{%
ifcsname tomasz@#1endcsname
expandafter@firstoftwo
else
expandafter@secondoftwo
fi
{csname tomasz@#1endcsname}%
{BUMMER!}%
}
makeatother
This is a job for csname
:
newcommand{setfoo}[2]{%
expandafternewcommandcsname tomasz@#1endcsname{#2}%
}
newcommand{foo}[1]{csname tomasz@#1endcsname}
You might use a check in foo
that the command is actually defined:
makeatletter
newcommand{foo}[1]{%
ifcsname tomasz@#1endcsname
expandafter@firstoftwo
else
expandafter@secondoftwo
fi
{csname tomasz@#1endcsname}%
{BUMMER!}%
}
makeatother
answered Jan 22 at 23:49
egregegreg
716k8619033189
716k8619033189
add a comment |
add a comment |
In your special case, where foo
is always to process a single undelimited non-optional argument, you can probably apply some expansion trickery for "flushing" the tokens that form the current definition of foo
into the new definition of foo
—one of the expansion-tricks is (ab)using romannumeral
for triggering expansion until LaTeX has found the number 0. romannumeral
's underlying conversion-routine does "swallow" non-positive numbers while silently not delivering any token at all:
documentclass{article}
usepackage{ifthen}
newcommandPassFirstToSecond[2]{#2{#1}}%
newcommand{foo}[1]{There is no setting for value #1.}
newcommand{setfoo}[2]{%
expandafterPassFirstToSecond
expandafter{%
romannumeralexpandafterPassFirstToSecondexpandafter{foo{##1}}%
{0 ifthenelse{equal{##1}{#1}}{#2}}%
}{renewcommand{foo}[1]}%
}
parindent=0ex
parskip=bigskipamount
begin{document}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{a}{part1}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{b}{part2}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{c}{part3}
texttt{stringfoospace currently is defined as:\ meaningfoo}
hrulefill
Some testing:
verb|foo{a}| yields: foo{a}
verb|foo{b}| yields: foo{b}
verb|foo{c}| yields: foo{c}
verb|foo{y}| yields: foo{y}
end{document}
add a comment |
In your special case, where foo
is always to process a single undelimited non-optional argument, you can probably apply some expansion trickery for "flushing" the tokens that form the current definition of foo
into the new definition of foo
—one of the expansion-tricks is (ab)using romannumeral
for triggering expansion until LaTeX has found the number 0. romannumeral
's underlying conversion-routine does "swallow" non-positive numbers while silently not delivering any token at all:
documentclass{article}
usepackage{ifthen}
newcommandPassFirstToSecond[2]{#2{#1}}%
newcommand{foo}[1]{There is no setting for value #1.}
newcommand{setfoo}[2]{%
expandafterPassFirstToSecond
expandafter{%
romannumeralexpandafterPassFirstToSecondexpandafter{foo{##1}}%
{0 ifthenelse{equal{##1}{#1}}{#2}}%
}{renewcommand{foo}[1]}%
}
parindent=0ex
parskip=bigskipamount
begin{document}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{a}{part1}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{b}{part2}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{c}{part3}
texttt{stringfoospace currently is defined as:\ meaningfoo}
hrulefill
Some testing:
verb|foo{a}| yields: foo{a}
verb|foo{b}| yields: foo{b}
verb|foo{c}| yields: foo{c}
verb|foo{y}| yields: foo{y}
end{document}
add a comment |
In your special case, where foo
is always to process a single undelimited non-optional argument, you can probably apply some expansion trickery for "flushing" the tokens that form the current definition of foo
into the new definition of foo
—one of the expansion-tricks is (ab)using romannumeral
for triggering expansion until LaTeX has found the number 0. romannumeral
's underlying conversion-routine does "swallow" non-positive numbers while silently not delivering any token at all:
documentclass{article}
usepackage{ifthen}
newcommandPassFirstToSecond[2]{#2{#1}}%
newcommand{foo}[1]{There is no setting for value #1.}
newcommand{setfoo}[2]{%
expandafterPassFirstToSecond
expandafter{%
romannumeralexpandafterPassFirstToSecondexpandafter{foo{##1}}%
{0 ifthenelse{equal{##1}{#1}}{#2}}%
}{renewcommand{foo}[1]}%
}
parindent=0ex
parskip=bigskipamount
begin{document}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{a}{part1}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{b}{part2}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{c}{part3}
texttt{stringfoospace currently is defined as:\ meaningfoo}
hrulefill
Some testing:
verb|foo{a}| yields: foo{a}
verb|foo{b}| yields: foo{b}
verb|foo{c}| yields: foo{c}
verb|foo{y}| yields: foo{y}
end{document}
In your special case, where foo
is always to process a single undelimited non-optional argument, you can probably apply some expansion trickery for "flushing" the tokens that form the current definition of foo
into the new definition of foo
—one of the expansion-tricks is (ab)using romannumeral
for triggering expansion until LaTeX has found the number 0. romannumeral
's underlying conversion-routine does "swallow" non-positive numbers while silently not delivering any token at all:
documentclass{article}
usepackage{ifthen}
newcommandPassFirstToSecond[2]{#2{#1}}%
newcommand{foo}[1]{There is no setting for value #1.}
newcommand{setfoo}[2]{%
expandafterPassFirstToSecond
expandafter{%
romannumeralexpandafterPassFirstToSecondexpandafter{foo{##1}}%
{0 ifthenelse{equal{##1}{#1}}{#2}}%
}{renewcommand{foo}[1]}%
}
parindent=0ex
parskip=bigskipamount
begin{document}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{a}{part1}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{b}{part2}
texttt{stringfoospace currently is defined as:\ meaningfoo}
setfoo{c}{part3}
texttt{stringfoospace currently is defined as:\ meaningfoo}
hrulefill
Some testing:
verb|foo{a}| yields: foo{a}
verb|foo{b}| yields: foo{b}
verb|foo{c}| yields: foo{c}
verb|foo{y}| yields: foo{y}
end{document}
edited Jan 27 at 3:34
answered Jan 27 at 3:17
Ulrich DiezUlrich Diez
4,470616
4,470616
add a comment |
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f471399%2fdefining-a-command-part-by-part%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
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
Required, but never shown
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
Required, but never shown
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
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Welcome to TeX.SE!
– Kurt
Jan 22 at 23:58