Formatting output for newcommand with for loop
I have the following minimum example
documentclass[12pt]{article}
usepackage{pgffor}
newcommand{formatlist}[2]{ {x^#1} foreach x in {#2} {,x^x}}
begin{document}
$$formatlist{5}{6,7}$$
end{document}
The foreach loop creates what I want to output, however, in order to prevent having an extra comma somewhere, I had to incorporate a second argument to get the formatting right. Does someone know how to do this with a single argument? If there's a way to splice a given argument into two lists then this would be a simple fix, but I couldn't figure out how to do that.
macros foreach pgffor
add a comment |
I have the following minimum example
documentclass[12pt]{article}
usepackage{pgffor}
newcommand{formatlist}[2]{ {x^#1} foreach x in {#2} {,x^x}}
begin{document}
$$formatlist{5}{6,7}$$
end{document}
The foreach loop creates what I want to output, however, in order to prevent having an extra comma somewhere, I had to incorporate a second argument to get the formatting right. Does someone know how to do this with a single argument? If there's a way to splice a given argument into two lists then this would be a simple fix, but I couldn't figure out how to do that.
macros foreach pgffor
add a comment |
I have the following minimum example
documentclass[12pt]{article}
usepackage{pgffor}
newcommand{formatlist}[2]{ {x^#1} foreach x in {#2} {,x^x}}
begin{document}
$$formatlist{5}{6,7}$$
end{document}
The foreach loop creates what I want to output, however, in order to prevent having an extra comma somewhere, I had to incorporate a second argument to get the formatting right. Does someone know how to do this with a single argument? If there's a way to splice a given argument into two lists then this would be a simple fix, but I couldn't figure out how to do that.
macros foreach pgffor
I have the following minimum example
documentclass[12pt]{article}
usepackage{pgffor}
newcommand{formatlist}[2]{ {x^#1} foreach x in {#2} {,x^x}}
begin{document}
$$formatlist{5}{6,7}$$
end{document}
The foreach loop creates what I want to output, however, in order to prevent having an extra comma somewhere, I had to incorporate a second argument to get the formatting right. Does someone know how to do this with a single argument? If there's a way to splice a given argument into two lists then this would be a simple fix, but I couldn't figure out how to do that.
macros foreach pgffor
macros foreach pgffor
asked Feb 10 at 21:38
Scott WhiteScott White
132
132
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Welcome to TeX.SE! foreach allows you to see the count of an item, and ifnum can be used to distinguish between comma and no comma.
documentclass[12pt]{article}
usepackage{pgffor}
newcommand{formatlist}[1]{foreach X [count=Y] in {#1} {ifnumY=1
x^X
else
,x^X
fi}}
begin{document}
[formatlist{5,6,7}]
end{document}

Thanks! The count part really helps :)
– Scott White
Feb 10 at 22:13
@ScottWhite You're welcome! Please consider trading$$ ... $$for[ ... ].
– marmot
Feb 10 at 22:14
thanks for the reference!
– Scott White
Feb 10 at 22:18
1
You can movex^Xoutside the branch:ifnumY=1else,fi x^X
– Henri Menke
Feb 11 at 1:05
@HenriMenke You are right, thanks! (However, the point of this answer was more to say there is thecountoption andifnumto distinguish the first element from the rest.)
– marmot
Feb 11 at 1:10
add a comment |
You can accommodate both lists and ranges. I also added an optional argument to change the base.
The idea is that if the mandatory argument contains .., then it denotes a range. Otherwise it is supposed to be a list (with comma separators). In both cases the first term is detached and the others are printed with a comma before them.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{formatlist}{ O{x} >{SplitArgument{1}{..}}m }
{
scott_format_rangeorlist:nnn {#1} #2
}
seq_new:N l__scott_format_list_seq
tl_new:N l__scott_format_list_tl
cs_new_protected:Nn scott_format_rangeorlist:nnn
{
tl_if_novalue:nTF { #3 }
{% no range, assume list of values
scott_format_list:nn { #1 } { #2 }
}
{% range
scott_format_range:nnn { #1 } { #2 } { #3 }
}
}
cs_new_protected:Nn scott_format_list:nn
{
seq_set_from_clist:Nn l__scott_format_list_seq { #2 }
seq_pop_left:NN l__scott_format_list_seq l__scott_format_list_tl
% print the first term
#1^{l__scott_format_list_tl}
% print the other terms, with a comma
seq_map_inline:Nn l__scott_format_list_seq { , #1^{##1} }
}
cs_new_protected:Nn scott_format_range:nnn
{
#1^{#2}
int_step_inline:nnn { #2 + 1 } { #3 } { ,#1^{##1} }
}
ExplSyntaxOff
begin{document}
textbf{Ranges}
$formatlist{5..7}$
$formatlist{1..10}$
$formatlist[y]{3}$
$formatlist[z]{1..5}$
$formatlist{8..8}$
textbf{Lists}
$formatlist{2,3,4,6}$
$formatlist{2}$
$formatlist[y]{6,8,10}$
end{document}

The command
formatlistis declared to have an optional argument, with default valuex, and a mandatory argument; due to the “preprocessor”SplitArgument{1}{..}, this argument will be returned in the format{<A>}{<B>}, where<A>represents what comes before..and<B>what's after; in the case..doesn't appear,<B>will be something that will make the conditionalif_novalue:nTFto return true.Control is then passed to
scott_format_rangeorlist:nnn, which takes three arguments;#2will consist of two braced items, as explained before.scott_format_rangeorlist:nnnexamines the third argument; if it is the special item that makesif_novalue:nTFto return true, the first two arguments are passed toscott_format_list:nn(and#2is so assumed to be a comma separated list), otherwisescott_format_range:nnnis called.scott_format_list:nnchanges the comma separated list into a sequence, whose left item is then detached for being processed on its own and stored in a token list variable; then this first item is passed as exponent to#1(the base); next the sequence is mapped to print,#1^{##1}. In this context,##1represents the current item in the sequence.scott_format_range:nnnfirst prints#1^{#2}(here#2is the lower bound in the range); then it does a loop printing,#1^{##1}starting from#2+1up to#3; here##1is the current integer in the loop.The function
seq_map_inline:Nnloops over the sequence, executing each time the second argument with##1representing the current item.The function
int_step_inline:nnndoes a loop with step 1 from the integer given as first argument up to the integer given as second argument; each time the third argument is executed, with##1representing the current value.
Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)
– Scott White
Feb 10 at 22:28
@ScottWhite I added some explanations.
– egreg
Feb 11 at 0:19
Thanks for adding all the explanation!
– Scott White
yesterday
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%2f474237%2fformatting-output-for-newcommand-with-for-loop%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
Welcome to TeX.SE! foreach allows you to see the count of an item, and ifnum can be used to distinguish between comma and no comma.
documentclass[12pt]{article}
usepackage{pgffor}
newcommand{formatlist}[1]{foreach X [count=Y] in {#1} {ifnumY=1
x^X
else
,x^X
fi}}
begin{document}
[formatlist{5,6,7}]
end{document}

Thanks! The count part really helps :)
– Scott White
Feb 10 at 22:13
@ScottWhite You're welcome! Please consider trading$$ ... $$for[ ... ].
– marmot
Feb 10 at 22:14
thanks for the reference!
– Scott White
Feb 10 at 22:18
1
You can movex^Xoutside the branch:ifnumY=1else,fi x^X
– Henri Menke
Feb 11 at 1:05
@HenriMenke You are right, thanks! (However, the point of this answer was more to say there is thecountoption andifnumto distinguish the first element from the rest.)
– marmot
Feb 11 at 1:10
add a comment |
Welcome to TeX.SE! foreach allows you to see the count of an item, and ifnum can be used to distinguish between comma and no comma.
documentclass[12pt]{article}
usepackage{pgffor}
newcommand{formatlist}[1]{foreach X [count=Y] in {#1} {ifnumY=1
x^X
else
,x^X
fi}}
begin{document}
[formatlist{5,6,7}]
end{document}

Thanks! The count part really helps :)
– Scott White
Feb 10 at 22:13
@ScottWhite You're welcome! Please consider trading$$ ... $$for[ ... ].
– marmot
Feb 10 at 22:14
thanks for the reference!
– Scott White
Feb 10 at 22:18
1
You can movex^Xoutside the branch:ifnumY=1else,fi x^X
– Henri Menke
Feb 11 at 1:05
@HenriMenke You are right, thanks! (However, the point of this answer was more to say there is thecountoption andifnumto distinguish the first element from the rest.)
– marmot
Feb 11 at 1:10
add a comment |
Welcome to TeX.SE! foreach allows you to see the count of an item, and ifnum can be used to distinguish between comma and no comma.
documentclass[12pt]{article}
usepackage{pgffor}
newcommand{formatlist}[1]{foreach X [count=Y] in {#1} {ifnumY=1
x^X
else
,x^X
fi}}
begin{document}
[formatlist{5,6,7}]
end{document}

Welcome to TeX.SE! foreach allows you to see the count of an item, and ifnum can be used to distinguish between comma and no comma.
documentclass[12pt]{article}
usepackage{pgffor}
newcommand{formatlist}[1]{foreach X [count=Y] in {#1} {ifnumY=1
x^X
else
,x^X
fi}}
begin{document}
[formatlist{5,6,7}]
end{document}

answered Feb 10 at 21:47
marmotmarmot
101k4116224
101k4116224
Thanks! The count part really helps :)
– Scott White
Feb 10 at 22:13
@ScottWhite You're welcome! Please consider trading$$ ... $$for[ ... ].
– marmot
Feb 10 at 22:14
thanks for the reference!
– Scott White
Feb 10 at 22:18
1
You can movex^Xoutside the branch:ifnumY=1else,fi x^X
– Henri Menke
Feb 11 at 1:05
@HenriMenke You are right, thanks! (However, the point of this answer was more to say there is thecountoption andifnumto distinguish the first element from the rest.)
– marmot
Feb 11 at 1:10
add a comment |
Thanks! The count part really helps :)
– Scott White
Feb 10 at 22:13
@ScottWhite You're welcome! Please consider trading$$ ... $$for[ ... ].
– marmot
Feb 10 at 22:14
thanks for the reference!
– Scott White
Feb 10 at 22:18
1
You can movex^Xoutside the branch:ifnumY=1else,fi x^X
– Henri Menke
Feb 11 at 1:05
@HenriMenke You are right, thanks! (However, the point of this answer was more to say there is thecountoption andifnumto distinguish the first element from the rest.)
– marmot
Feb 11 at 1:10
Thanks! The count part really helps :)
– Scott White
Feb 10 at 22:13
Thanks! The count part really helps :)
– Scott White
Feb 10 at 22:13
@ScottWhite You're welcome! Please consider trading
$$ ... $$ for [ ... ].– marmot
Feb 10 at 22:14
@ScottWhite You're welcome! Please consider trading
$$ ... $$ for [ ... ].– marmot
Feb 10 at 22:14
thanks for the reference!
– Scott White
Feb 10 at 22:18
thanks for the reference!
– Scott White
Feb 10 at 22:18
1
1
You can move
x^X outside the branch: ifnumY=1else,fi x^X– Henri Menke
Feb 11 at 1:05
You can move
x^X outside the branch: ifnumY=1else,fi x^X– Henri Menke
Feb 11 at 1:05
@HenriMenke You are right, thanks! (However, the point of this answer was more to say there is the
count option and ifnum to distinguish the first element from the rest.)– marmot
Feb 11 at 1:10
@HenriMenke You are right, thanks! (However, the point of this answer was more to say there is the
count option and ifnum to distinguish the first element from the rest.)– marmot
Feb 11 at 1:10
add a comment |
You can accommodate both lists and ranges. I also added an optional argument to change the base.
The idea is that if the mandatory argument contains .., then it denotes a range. Otherwise it is supposed to be a list (with comma separators). In both cases the first term is detached and the others are printed with a comma before them.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{formatlist}{ O{x} >{SplitArgument{1}{..}}m }
{
scott_format_rangeorlist:nnn {#1} #2
}
seq_new:N l__scott_format_list_seq
tl_new:N l__scott_format_list_tl
cs_new_protected:Nn scott_format_rangeorlist:nnn
{
tl_if_novalue:nTF { #3 }
{% no range, assume list of values
scott_format_list:nn { #1 } { #2 }
}
{% range
scott_format_range:nnn { #1 } { #2 } { #3 }
}
}
cs_new_protected:Nn scott_format_list:nn
{
seq_set_from_clist:Nn l__scott_format_list_seq { #2 }
seq_pop_left:NN l__scott_format_list_seq l__scott_format_list_tl
% print the first term
#1^{l__scott_format_list_tl}
% print the other terms, with a comma
seq_map_inline:Nn l__scott_format_list_seq { , #1^{##1} }
}
cs_new_protected:Nn scott_format_range:nnn
{
#1^{#2}
int_step_inline:nnn { #2 + 1 } { #3 } { ,#1^{##1} }
}
ExplSyntaxOff
begin{document}
textbf{Ranges}
$formatlist{5..7}$
$formatlist{1..10}$
$formatlist[y]{3}$
$formatlist[z]{1..5}$
$formatlist{8..8}$
textbf{Lists}
$formatlist{2,3,4,6}$
$formatlist{2}$
$formatlist[y]{6,8,10}$
end{document}

The command
formatlistis declared to have an optional argument, with default valuex, and a mandatory argument; due to the “preprocessor”SplitArgument{1}{..}, this argument will be returned in the format{<A>}{<B>}, where<A>represents what comes before..and<B>what's after; in the case..doesn't appear,<B>will be something that will make the conditionalif_novalue:nTFto return true.Control is then passed to
scott_format_rangeorlist:nnn, which takes three arguments;#2will consist of two braced items, as explained before.scott_format_rangeorlist:nnnexamines the third argument; if it is the special item that makesif_novalue:nTFto return true, the first two arguments are passed toscott_format_list:nn(and#2is so assumed to be a comma separated list), otherwisescott_format_range:nnnis called.scott_format_list:nnchanges the comma separated list into a sequence, whose left item is then detached for being processed on its own and stored in a token list variable; then this first item is passed as exponent to#1(the base); next the sequence is mapped to print,#1^{##1}. In this context,##1represents the current item in the sequence.scott_format_range:nnnfirst prints#1^{#2}(here#2is the lower bound in the range); then it does a loop printing,#1^{##1}starting from#2+1up to#3; here##1is the current integer in the loop.The function
seq_map_inline:Nnloops over the sequence, executing each time the second argument with##1representing the current item.The function
int_step_inline:nnndoes a loop with step 1 from the integer given as first argument up to the integer given as second argument; each time the third argument is executed, with##1representing the current value.
Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)
– Scott White
Feb 10 at 22:28
@ScottWhite I added some explanations.
– egreg
Feb 11 at 0:19
Thanks for adding all the explanation!
– Scott White
yesterday
add a comment |
You can accommodate both lists and ranges. I also added an optional argument to change the base.
The idea is that if the mandatory argument contains .., then it denotes a range. Otherwise it is supposed to be a list (with comma separators). In both cases the first term is detached and the others are printed with a comma before them.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{formatlist}{ O{x} >{SplitArgument{1}{..}}m }
{
scott_format_rangeorlist:nnn {#1} #2
}
seq_new:N l__scott_format_list_seq
tl_new:N l__scott_format_list_tl
cs_new_protected:Nn scott_format_rangeorlist:nnn
{
tl_if_novalue:nTF { #3 }
{% no range, assume list of values
scott_format_list:nn { #1 } { #2 }
}
{% range
scott_format_range:nnn { #1 } { #2 } { #3 }
}
}
cs_new_protected:Nn scott_format_list:nn
{
seq_set_from_clist:Nn l__scott_format_list_seq { #2 }
seq_pop_left:NN l__scott_format_list_seq l__scott_format_list_tl
% print the first term
#1^{l__scott_format_list_tl}
% print the other terms, with a comma
seq_map_inline:Nn l__scott_format_list_seq { , #1^{##1} }
}
cs_new_protected:Nn scott_format_range:nnn
{
#1^{#2}
int_step_inline:nnn { #2 + 1 } { #3 } { ,#1^{##1} }
}
ExplSyntaxOff
begin{document}
textbf{Ranges}
$formatlist{5..7}$
$formatlist{1..10}$
$formatlist[y]{3}$
$formatlist[z]{1..5}$
$formatlist{8..8}$
textbf{Lists}
$formatlist{2,3,4,6}$
$formatlist{2}$
$formatlist[y]{6,8,10}$
end{document}

The command
formatlistis declared to have an optional argument, with default valuex, and a mandatory argument; due to the “preprocessor”SplitArgument{1}{..}, this argument will be returned in the format{<A>}{<B>}, where<A>represents what comes before..and<B>what's after; in the case..doesn't appear,<B>will be something that will make the conditionalif_novalue:nTFto return true.Control is then passed to
scott_format_rangeorlist:nnn, which takes three arguments;#2will consist of two braced items, as explained before.scott_format_rangeorlist:nnnexamines the third argument; if it is the special item that makesif_novalue:nTFto return true, the first two arguments are passed toscott_format_list:nn(and#2is so assumed to be a comma separated list), otherwisescott_format_range:nnnis called.scott_format_list:nnchanges the comma separated list into a sequence, whose left item is then detached for being processed on its own and stored in a token list variable; then this first item is passed as exponent to#1(the base); next the sequence is mapped to print,#1^{##1}. In this context,##1represents the current item in the sequence.scott_format_range:nnnfirst prints#1^{#2}(here#2is the lower bound in the range); then it does a loop printing,#1^{##1}starting from#2+1up to#3; here##1is the current integer in the loop.The function
seq_map_inline:Nnloops over the sequence, executing each time the second argument with##1representing the current item.The function
int_step_inline:nnndoes a loop with step 1 from the integer given as first argument up to the integer given as second argument; each time the third argument is executed, with##1representing the current value.
Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)
– Scott White
Feb 10 at 22:28
@ScottWhite I added some explanations.
– egreg
Feb 11 at 0:19
Thanks for adding all the explanation!
– Scott White
yesterday
add a comment |
You can accommodate both lists and ranges. I also added an optional argument to change the base.
The idea is that if the mandatory argument contains .., then it denotes a range. Otherwise it is supposed to be a list (with comma separators). In both cases the first term is detached and the others are printed with a comma before them.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{formatlist}{ O{x} >{SplitArgument{1}{..}}m }
{
scott_format_rangeorlist:nnn {#1} #2
}
seq_new:N l__scott_format_list_seq
tl_new:N l__scott_format_list_tl
cs_new_protected:Nn scott_format_rangeorlist:nnn
{
tl_if_novalue:nTF { #3 }
{% no range, assume list of values
scott_format_list:nn { #1 } { #2 }
}
{% range
scott_format_range:nnn { #1 } { #2 } { #3 }
}
}
cs_new_protected:Nn scott_format_list:nn
{
seq_set_from_clist:Nn l__scott_format_list_seq { #2 }
seq_pop_left:NN l__scott_format_list_seq l__scott_format_list_tl
% print the first term
#1^{l__scott_format_list_tl}
% print the other terms, with a comma
seq_map_inline:Nn l__scott_format_list_seq { , #1^{##1} }
}
cs_new_protected:Nn scott_format_range:nnn
{
#1^{#2}
int_step_inline:nnn { #2 + 1 } { #3 } { ,#1^{##1} }
}
ExplSyntaxOff
begin{document}
textbf{Ranges}
$formatlist{5..7}$
$formatlist{1..10}$
$formatlist[y]{3}$
$formatlist[z]{1..5}$
$formatlist{8..8}$
textbf{Lists}
$formatlist{2,3,4,6}$
$formatlist{2}$
$formatlist[y]{6,8,10}$
end{document}

The command
formatlistis declared to have an optional argument, with default valuex, and a mandatory argument; due to the “preprocessor”SplitArgument{1}{..}, this argument will be returned in the format{<A>}{<B>}, where<A>represents what comes before..and<B>what's after; in the case..doesn't appear,<B>will be something that will make the conditionalif_novalue:nTFto return true.Control is then passed to
scott_format_rangeorlist:nnn, which takes three arguments;#2will consist of two braced items, as explained before.scott_format_rangeorlist:nnnexamines the third argument; if it is the special item that makesif_novalue:nTFto return true, the first two arguments are passed toscott_format_list:nn(and#2is so assumed to be a comma separated list), otherwisescott_format_range:nnnis called.scott_format_list:nnchanges the comma separated list into a sequence, whose left item is then detached for being processed on its own and stored in a token list variable; then this first item is passed as exponent to#1(the base); next the sequence is mapped to print,#1^{##1}. In this context,##1represents the current item in the sequence.scott_format_range:nnnfirst prints#1^{#2}(here#2is the lower bound in the range); then it does a loop printing,#1^{##1}starting from#2+1up to#3; here##1is the current integer in the loop.The function
seq_map_inline:Nnloops over the sequence, executing each time the second argument with##1representing the current item.The function
int_step_inline:nnndoes a loop with step 1 from the integer given as first argument up to the integer given as second argument; each time the third argument is executed, with##1representing the current value.
You can accommodate both lists and ranges. I also added an optional argument to change the base.
The idea is that if the mandatory argument contains .., then it denotes a range. Otherwise it is supposed to be a list (with comma separators). In both cases the first term is detached and the others are printed with a comma before them.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{formatlist}{ O{x} >{SplitArgument{1}{..}}m }
{
scott_format_rangeorlist:nnn {#1} #2
}
seq_new:N l__scott_format_list_seq
tl_new:N l__scott_format_list_tl
cs_new_protected:Nn scott_format_rangeorlist:nnn
{
tl_if_novalue:nTF { #3 }
{% no range, assume list of values
scott_format_list:nn { #1 } { #2 }
}
{% range
scott_format_range:nnn { #1 } { #2 } { #3 }
}
}
cs_new_protected:Nn scott_format_list:nn
{
seq_set_from_clist:Nn l__scott_format_list_seq { #2 }
seq_pop_left:NN l__scott_format_list_seq l__scott_format_list_tl
% print the first term
#1^{l__scott_format_list_tl}
% print the other terms, with a comma
seq_map_inline:Nn l__scott_format_list_seq { , #1^{##1} }
}
cs_new_protected:Nn scott_format_range:nnn
{
#1^{#2}
int_step_inline:nnn { #2 + 1 } { #3 } { ,#1^{##1} }
}
ExplSyntaxOff
begin{document}
textbf{Ranges}
$formatlist{5..7}$
$formatlist{1..10}$
$formatlist[y]{3}$
$formatlist[z]{1..5}$
$formatlist{8..8}$
textbf{Lists}
$formatlist{2,3,4,6}$
$formatlist{2}$
$formatlist[y]{6,8,10}$
end{document}

The command
formatlistis declared to have an optional argument, with default valuex, and a mandatory argument; due to the “preprocessor”SplitArgument{1}{..}, this argument will be returned in the format{<A>}{<B>}, where<A>represents what comes before..and<B>what's after; in the case..doesn't appear,<B>will be something that will make the conditionalif_novalue:nTFto return true.Control is then passed to
scott_format_rangeorlist:nnn, which takes three arguments;#2will consist of two braced items, as explained before.scott_format_rangeorlist:nnnexamines the third argument; if it is the special item that makesif_novalue:nTFto return true, the first two arguments are passed toscott_format_list:nn(and#2is so assumed to be a comma separated list), otherwisescott_format_range:nnnis called.scott_format_list:nnchanges the comma separated list into a sequence, whose left item is then detached for being processed on its own and stored in a token list variable; then this first item is passed as exponent to#1(the base); next the sequence is mapped to print,#1^{##1}. In this context,##1represents the current item in the sequence.scott_format_range:nnnfirst prints#1^{#2}(here#2is the lower bound in the range); then it does a loop printing,#1^{##1}starting from#2+1up to#3; here##1is the current integer in the loop.The function
seq_map_inline:Nnloops over the sequence, executing each time the second argument with##1representing the current item.The function
int_step_inline:nnndoes a loop with step 1 from the integer given as first argument up to the integer given as second argument; each time the third argument is executed, with##1representing the current value.
edited Feb 11 at 0:18
answered Feb 10 at 22:17
egregegreg
720k8719093208
720k8719093208
Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)
– Scott White
Feb 10 at 22:28
@ScottWhite I added some explanations.
– egreg
Feb 11 at 0:19
Thanks for adding all the explanation!
– Scott White
yesterday
add a comment |
Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)
– Scott White
Feb 10 at 22:28
@ScottWhite I added some explanations.
– egreg
Feb 11 at 0:19
Thanks for adding all the explanation!
– Scott White
yesterday
Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)
– Scott White
Feb 10 at 22:28
Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)
– Scott White
Feb 10 at 22:28
@ScottWhite I added some explanations.
– egreg
Feb 11 at 0:19
@ScottWhite I added some explanations.
– egreg
Feb 11 at 0:19
Thanks for adding all the explanation!
– Scott White
yesterday
Thanks for adding all the explanation!
– Scott White
yesterday
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%2f474237%2fformatting-output-for-newcommand-with-for-loop%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