Prevent newline after clist_map_inline
up vote
5
down vote
favorite
I'm trying to automate the creation of some forms, and part of that
effort is automatically creating the correct number of blank rows in a
table-like form. That's led me to the following strange behavior:
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
cs_new_eq:NN clistMap clist_map_inline:nn
ExplSyntaxOff
begin{document}
begin{tabular}{|ll|}
clistMap{one, two, three}{#1 &\hline}
end{tabular}
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
The two tables are typeset differently. I don't understand why.
There's a trailing row after the three rows in the first table. I say
a trailing row, because this following table is typeset the same as
the first.
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
\
end{tabular}
As one final pair of examples, as minimal as possible, note the same
appearance of the following two tables:
begin{tabular}{|ll|}
clistMap{}{#1 &\hline}
end{tabular}
medskip % So you can see where one table ends and the other begins.
begin{tabular}{|ll|}
\
end{tabular}
How do I get rid of this trailing newline? For bonus points---If you'd
be so kind, future answerers of mine---how would one detect that some
other unexpected control sequences are there? I tried using fancyvrb
commands to do it, and I could never quite get what I wanted; I wasn't
able to detect the \
control sequence, and other characters like
&
caused problems. I also tried using the trace package, something
like clistMap
expands to around 1000 lines of expanded macros.
latex3
|
show 5 more comments
up vote
5
down vote
favorite
I'm trying to automate the creation of some forms, and part of that
effort is automatically creating the correct number of blank rows in a
table-like form. That's led me to the following strange behavior:
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
cs_new_eq:NN clistMap clist_map_inline:nn
ExplSyntaxOff
begin{document}
begin{tabular}{|ll|}
clistMap{one, two, three}{#1 &\hline}
end{tabular}
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
The two tables are typeset differently. I don't understand why.
There's a trailing row after the three rows in the first table. I say
a trailing row, because this following table is typeset the same as
the first.
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
\
end{tabular}
As one final pair of examples, as minimal as possible, note the same
appearance of the following two tables:
begin{tabular}{|ll|}
clistMap{}{#1 &\hline}
end{tabular}
medskip % So you can see where one table ends and the other begins.
begin{tabular}{|ll|}
\
end{tabular}
How do I get rid of this trailing newline? For bonus points---If you'd
be so kind, future answerers of mine---how would one detect that some
other unexpected control sequences are there? I tried using fancyvrb
commands to do it, and I could never quite get what I wanted; I wasn't
able to detect the \
control sequence, and other characters like
&
caused problems. I also tried using the trace package, something
like clistMap
expands to around 1000 lines of expanded macros.
latex3
If you useclist_map_function:nN
instead it works (don't ask me why, though :)
– Phelype Oleinik
Nov 28 at 21:44
3
you do not have an extra\
to see the effect just userelax
or{}
orhline
in your second table.
– David Carlisle
Nov 28 at 21:45
2
clist_map_inline:nn
is not expandable and will leave something behind the last hline which create a new line.
– Ulrike Fischer
Nov 28 at 21:47
1
in your first code block you have two tables which have different output, the first has a extra spurious row, but that is not because the l3 code generated an extra\
, addrelax
beforeend{tabular}
to the second tabular then the two will produce the same output.
– David Carlisle
Nov 28 at 22:21
1
@Beelzebielsk yes anything in that position will start a cell and so a row, an assignment likerefstepcounter
or justrelax
(which does nothing) the only things in that position that do not start a new row have to expand to nothing, like@empty
– David Carlisle
Nov 28 at 22:30
|
show 5 more comments
up vote
5
down vote
favorite
up vote
5
down vote
favorite
I'm trying to automate the creation of some forms, and part of that
effort is automatically creating the correct number of blank rows in a
table-like form. That's led me to the following strange behavior:
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
cs_new_eq:NN clistMap clist_map_inline:nn
ExplSyntaxOff
begin{document}
begin{tabular}{|ll|}
clistMap{one, two, three}{#1 &\hline}
end{tabular}
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
The two tables are typeset differently. I don't understand why.
There's a trailing row after the three rows in the first table. I say
a trailing row, because this following table is typeset the same as
the first.
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
\
end{tabular}
As one final pair of examples, as minimal as possible, note the same
appearance of the following two tables:
begin{tabular}{|ll|}
clistMap{}{#1 &\hline}
end{tabular}
medskip % So you can see where one table ends and the other begins.
begin{tabular}{|ll|}
\
end{tabular}
How do I get rid of this trailing newline? For bonus points---If you'd
be so kind, future answerers of mine---how would one detect that some
other unexpected control sequences are there? I tried using fancyvrb
commands to do it, and I could never quite get what I wanted; I wasn't
able to detect the \
control sequence, and other characters like
&
caused problems. I also tried using the trace package, something
like clistMap
expands to around 1000 lines of expanded macros.
latex3
I'm trying to automate the creation of some forms, and part of that
effort is automatically creating the correct number of blank rows in a
table-like form. That's led me to the following strange behavior:
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
cs_new_eq:NN clistMap clist_map_inline:nn
ExplSyntaxOff
begin{document}
begin{tabular}{|ll|}
clistMap{one, two, three}{#1 &\hline}
end{tabular}
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
The two tables are typeset differently. I don't understand why.
There's a trailing row after the three rows in the first table. I say
a trailing row, because this following table is typeset the same as
the first.
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
\
end{tabular}
As one final pair of examples, as minimal as possible, note the same
appearance of the following two tables:
begin{tabular}{|ll|}
clistMap{}{#1 &\hline}
end{tabular}
medskip % So you can see where one table ends and the other begins.
begin{tabular}{|ll|}
\
end{tabular}
How do I get rid of this trailing newline? For bonus points---If you'd
be so kind, future answerers of mine---how would one detect that some
other unexpected control sequences are there? I tried using fancyvrb
commands to do it, and I could never quite get what I wanted; I wasn't
able to detect the \
control sequence, and other characters like
&
caused problems. I also tried using the trace package, something
like clistMap
expands to around 1000 lines of expanded macros.
latex3
latex3
edited Nov 28 at 22:08
asked Nov 28 at 21:39
Beelzebielsk
306
306
If you useclist_map_function:nN
instead it works (don't ask me why, though :)
– Phelype Oleinik
Nov 28 at 21:44
3
you do not have an extra\
to see the effect just userelax
or{}
orhline
in your second table.
– David Carlisle
Nov 28 at 21:45
2
clist_map_inline:nn
is not expandable and will leave something behind the last hline which create a new line.
– Ulrike Fischer
Nov 28 at 21:47
1
in your first code block you have two tables which have different output, the first has a extra spurious row, but that is not because the l3 code generated an extra\
, addrelax
beforeend{tabular}
to the second tabular then the two will produce the same output.
– David Carlisle
Nov 28 at 22:21
1
@Beelzebielsk yes anything in that position will start a cell and so a row, an assignment likerefstepcounter
or justrelax
(which does nothing) the only things in that position that do not start a new row have to expand to nothing, like@empty
– David Carlisle
Nov 28 at 22:30
|
show 5 more comments
If you useclist_map_function:nN
instead it works (don't ask me why, though :)
– Phelype Oleinik
Nov 28 at 21:44
3
you do not have an extra\
to see the effect just userelax
or{}
orhline
in your second table.
– David Carlisle
Nov 28 at 21:45
2
clist_map_inline:nn
is not expandable and will leave something behind the last hline which create a new line.
– Ulrike Fischer
Nov 28 at 21:47
1
in your first code block you have two tables which have different output, the first has a extra spurious row, but that is not because the l3 code generated an extra\
, addrelax
beforeend{tabular}
to the second tabular then the two will produce the same output.
– David Carlisle
Nov 28 at 22:21
1
@Beelzebielsk yes anything in that position will start a cell and so a row, an assignment likerefstepcounter
or justrelax
(which does nothing) the only things in that position that do not start a new row have to expand to nothing, like@empty
– David Carlisle
Nov 28 at 22:30
If you use
clist_map_function:nN
instead it works (don't ask me why, though :)– Phelype Oleinik
Nov 28 at 21:44
If you use
clist_map_function:nN
instead it works (don't ask me why, though :)– Phelype Oleinik
Nov 28 at 21:44
3
3
you do not have an extra
\
to see the effect just use relax
or {}
or
or more or less anything at all after the final hline
in your second table.– David Carlisle
Nov 28 at 21:45
you do not have an extra
\
to see the effect just use relax
or {}
or
or more or less anything at all after the final hline
in your second table.– David Carlisle
Nov 28 at 21:45
2
2
clist_map_inline:nn
is not expandable and will leave something behind the last hline which create a new line.– Ulrike Fischer
Nov 28 at 21:47
clist_map_inline:nn
is not expandable and will leave something behind the last hline which create a new line.– Ulrike Fischer
Nov 28 at 21:47
1
1
in your first code block you have two tables which have different output, the first has a extra spurious row, but that is not because the l3 code generated an extra
\
, add relax
before end{tabular}
to the second tabular then the two will produce the same output.– David Carlisle
Nov 28 at 22:21
in your first code block you have two tables which have different output, the first has a extra spurious row, but that is not because the l3 code generated an extra
\
, add relax
before end{tabular}
to the second tabular then the two will produce the same output.– David Carlisle
Nov 28 at 22:21
1
1
@Beelzebielsk yes anything in that position will start a cell and so a row, an assignment like
refstepcounter
or just relax
(which does nothing) the only things in that position that do not start a new row have to expand to nothing, like @empty
– David Carlisle
Nov 28 at 22:30
@Beelzebielsk yes anything in that position will start a cell and so a row, an assignment like
refstepcounter
or just relax
(which does nothing) the only things in that position that do not start a new row have to expand to nothing, like @empty
– David Carlisle
Nov 28 at 22:30
|
show 5 more comments
3 Answers
3
active
oldest
votes
up vote
6
down vote
accepted
You need to use clist_map_function:nN
, defining a temporary function:
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{clistMap}{mm}
{
cs_gset:Nn __beelzebielsk_map:n { #2 }
clist_map_function:nN { #1 } __beelzebielsk_map:n
}
ExplSyntaxOff
begin{document}
begin{tabular}{|l|l|}
hline
clistMap{one, two, three}{#1 &\hline}
end{tabular}
qquad
begin{tabular}{|l|l|}
hline
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
The problem with clist_map_inline:nn
is that it leaves TeX in the state where a new cell has already been started when it realizes that the loop has ended.
This is actually what clist_map_inline:nn
does: it defines a new “unnamed” function and does clist_map_function:nN
with it. However it also has to cover its tracks, particularly for being usable also nested, and for this it uses a counter that has to be stepped down at the end: this is the operation that creates the unwanted additional row.
More explicitly: clist_map_inline:nn { <clist> } { <code> }
roughly does
int_incr:Nn <reserved>_int
cs_gset:cn { <reserved> int_eval:n <reserved>_int :n } { <code> }
clist_map_function:nc { <clist> } { <reserved> int_eval:n <reserved>_int :n }
int_decr:Nn <reserved>_int
The function passed to clist_map_function:nc
so depends on the nesting level, because the reserved counter is associated to clist mappings. This allows clist_map_inline:nn
to contain in its second argument an inner clist_map_inline:nn
, which will execute clist_map_function:nc
with a different function.
However, the int_decr:Nn <reserved>_int
operation will trigger, in your case, TeX starting a new cell. TeX tables are always rebellious beasts. ;-)
.
With the proposed definition, the operations on counters are skipped; of course you cannot nest clistMap
in clistMap
.
Could you explain why there's this difference betweenclist_map_function:nN
andclist_map_inline:nn
? There's nothing obvious to me about why one would have to leave a little extra stuff after the loop and the other doesn't. A reference for my familiarity: I've used TeX for several years, and I've read a few chapters of the TeXBook. I still find TeX and all related things extremely obtuse (once I want to start creating things of my own). Overall, not that familiar with the internals, TeX primitives, nor with Latex3.
– Beelzebielsk
Nov 28 at 22:41
@Beelzebielsk I added some more explanations
– egreg
Nov 28 at 22:54
It is an interesting question if that could be avoided somehow in the inline versions (I guess that is the same with all other functions of that nature too). If not it might be something that is worth documenting
– Frank Mittelbach
Nov 30 at 10:51
@FrankMittelbach I'm curious as to how you'd document this. I doubt you'd just say, "Careful using it with tables!" since I get the feeling that this detail could affect the display of other things. However, if you just said something more general to the effect of "the inline variant leaves stuff after the last iteration", I wouldn't understand that this could affect table typesetting. I struggle with TeX and LaTeX because the connections between various things is not obvious, and I stumble haphazardly onto those connections by reading books and random stackexchange posts.
– Beelzebielsk
2 days ago
@FrankMittelbach To say this another way, if the documentation already said, "The inline variants leave other stuff after the last iteration," I'd have still posted this question.
– Beelzebielsk
2 days ago
|
show 1 more comment
up vote
3
down vote
I am sure everyone will forgive my somewhat off-topic answer, and this is just to provide an example illustrating @egreg explanations:
documentclass{article}
usepackage{xinttools}
begin{document}
begin{tabular}{|ll|}
hline
xintFor #1 in {one, two, three}:
{#1 &\hline}
end{tabular}
begin{tabular}{|ll|}
hline
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
Although xintFor
acts non-expandably, it is careful not to do anything "non vanishing by pure expansion" at its end. This allows it to not trigger accidentally a new row. This constraint does however have some limitation effect on the features of xintFor
(see the boxed "15.17 xintifForFirst, xintifForLast" comments in xint.pdf).
Notice that the xintFor
nests well.
A side remark here is about the strange "gaps" one sees (when magnifying) at the joining of horizontal and vertical lines in both (identical) tabulars: add usepackage{array}
to fix that.
It's actually not that off-topic. The main goal of this question was to automate the creation of tabular-style forms. This is another method toward that approach. Though, I'm preferring the LaTeX3 stuff.
– Beelzebielsk
Nov 30 at 0:44
add a comment |
up vote
3
down vote
You could make the original function safe in this position by use of noalign
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
cs_new_eq:NN clistMap clist_map_inline:nn
ExplSyntaxOff
begin{document}
begin{tabular}{|ll|}
noalignbgroupclistMap{one, two, three}{egroup#1 &\hlinenoalignbgroup}egroup
end{tabular}
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
Yes, I noticed that, I was not referring to the actual item being scoped but only to the additional dealings ofclist_map_inline:nn
in-between (if any) and after the last iteration.
– jfbu
Nov 30 at 17:10
@jfbu ah OK I'd have to check what it's really doing (or you could ask Joseph in chat:-)
– David Carlisle
Nov 30 at 17:35
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
6
down vote
accepted
You need to use clist_map_function:nN
, defining a temporary function:
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{clistMap}{mm}
{
cs_gset:Nn __beelzebielsk_map:n { #2 }
clist_map_function:nN { #1 } __beelzebielsk_map:n
}
ExplSyntaxOff
begin{document}
begin{tabular}{|l|l|}
hline
clistMap{one, two, three}{#1 &\hline}
end{tabular}
qquad
begin{tabular}{|l|l|}
hline
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
The problem with clist_map_inline:nn
is that it leaves TeX in the state where a new cell has already been started when it realizes that the loop has ended.
This is actually what clist_map_inline:nn
does: it defines a new “unnamed” function and does clist_map_function:nN
with it. However it also has to cover its tracks, particularly for being usable also nested, and for this it uses a counter that has to be stepped down at the end: this is the operation that creates the unwanted additional row.
More explicitly: clist_map_inline:nn { <clist> } { <code> }
roughly does
int_incr:Nn <reserved>_int
cs_gset:cn { <reserved> int_eval:n <reserved>_int :n } { <code> }
clist_map_function:nc { <clist> } { <reserved> int_eval:n <reserved>_int :n }
int_decr:Nn <reserved>_int
The function passed to clist_map_function:nc
so depends on the nesting level, because the reserved counter is associated to clist mappings. This allows clist_map_inline:nn
to contain in its second argument an inner clist_map_inline:nn
, which will execute clist_map_function:nc
with a different function.
However, the int_decr:Nn <reserved>_int
operation will trigger, in your case, TeX starting a new cell. TeX tables are always rebellious beasts. ;-)
.
With the proposed definition, the operations on counters are skipped; of course you cannot nest clistMap
in clistMap
.
Could you explain why there's this difference betweenclist_map_function:nN
andclist_map_inline:nn
? There's nothing obvious to me about why one would have to leave a little extra stuff after the loop and the other doesn't. A reference for my familiarity: I've used TeX for several years, and I've read a few chapters of the TeXBook. I still find TeX and all related things extremely obtuse (once I want to start creating things of my own). Overall, not that familiar with the internals, TeX primitives, nor with Latex3.
– Beelzebielsk
Nov 28 at 22:41
@Beelzebielsk I added some more explanations
– egreg
Nov 28 at 22:54
It is an interesting question if that could be avoided somehow in the inline versions (I guess that is the same with all other functions of that nature too). If not it might be something that is worth documenting
– Frank Mittelbach
Nov 30 at 10:51
@FrankMittelbach I'm curious as to how you'd document this. I doubt you'd just say, "Careful using it with tables!" since I get the feeling that this detail could affect the display of other things. However, if you just said something more general to the effect of "the inline variant leaves stuff after the last iteration", I wouldn't understand that this could affect table typesetting. I struggle with TeX and LaTeX because the connections between various things is not obvious, and I stumble haphazardly onto those connections by reading books and random stackexchange posts.
– Beelzebielsk
2 days ago
@FrankMittelbach To say this another way, if the documentation already said, "The inline variants leave other stuff after the last iteration," I'd have still posted this question.
– Beelzebielsk
2 days ago
|
show 1 more comment
up vote
6
down vote
accepted
You need to use clist_map_function:nN
, defining a temporary function:
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{clistMap}{mm}
{
cs_gset:Nn __beelzebielsk_map:n { #2 }
clist_map_function:nN { #1 } __beelzebielsk_map:n
}
ExplSyntaxOff
begin{document}
begin{tabular}{|l|l|}
hline
clistMap{one, two, three}{#1 &\hline}
end{tabular}
qquad
begin{tabular}{|l|l|}
hline
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
The problem with clist_map_inline:nn
is that it leaves TeX in the state where a new cell has already been started when it realizes that the loop has ended.
This is actually what clist_map_inline:nn
does: it defines a new “unnamed” function and does clist_map_function:nN
with it. However it also has to cover its tracks, particularly for being usable also nested, and for this it uses a counter that has to be stepped down at the end: this is the operation that creates the unwanted additional row.
More explicitly: clist_map_inline:nn { <clist> } { <code> }
roughly does
int_incr:Nn <reserved>_int
cs_gset:cn { <reserved> int_eval:n <reserved>_int :n } { <code> }
clist_map_function:nc { <clist> } { <reserved> int_eval:n <reserved>_int :n }
int_decr:Nn <reserved>_int
The function passed to clist_map_function:nc
so depends on the nesting level, because the reserved counter is associated to clist mappings. This allows clist_map_inline:nn
to contain in its second argument an inner clist_map_inline:nn
, which will execute clist_map_function:nc
with a different function.
However, the int_decr:Nn <reserved>_int
operation will trigger, in your case, TeX starting a new cell. TeX tables are always rebellious beasts. ;-)
.
With the proposed definition, the operations on counters are skipped; of course you cannot nest clistMap
in clistMap
.
Could you explain why there's this difference betweenclist_map_function:nN
andclist_map_inline:nn
? There's nothing obvious to me about why one would have to leave a little extra stuff after the loop and the other doesn't. A reference for my familiarity: I've used TeX for several years, and I've read a few chapters of the TeXBook. I still find TeX and all related things extremely obtuse (once I want to start creating things of my own). Overall, not that familiar with the internals, TeX primitives, nor with Latex3.
– Beelzebielsk
Nov 28 at 22:41
@Beelzebielsk I added some more explanations
– egreg
Nov 28 at 22:54
It is an interesting question if that could be avoided somehow in the inline versions (I guess that is the same with all other functions of that nature too). If not it might be something that is worth documenting
– Frank Mittelbach
Nov 30 at 10:51
@FrankMittelbach I'm curious as to how you'd document this. I doubt you'd just say, "Careful using it with tables!" since I get the feeling that this detail could affect the display of other things. However, if you just said something more general to the effect of "the inline variant leaves stuff after the last iteration", I wouldn't understand that this could affect table typesetting. I struggle with TeX and LaTeX because the connections between various things is not obvious, and I stumble haphazardly onto those connections by reading books and random stackexchange posts.
– Beelzebielsk
2 days ago
@FrankMittelbach To say this another way, if the documentation already said, "The inline variants leave other stuff after the last iteration," I'd have still posted this question.
– Beelzebielsk
2 days ago
|
show 1 more comment
up vote
6
down vote
accepted
up vote
6
down vote
accepted
You need to use clist_map_function:nN
, defining a temporary function:
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{clistMap}{mm}
{
cs_gset:Nn __beelzebielsk_map:n { #2 }
clist_map_function:nN { #1 } __beelzebielsk_map:n
}
ExplSyntaxOff
begin{document}
begin{tabular}{|l|l|}
hline
clistMap{one, two, three}{#1 &\hline}
end{tabular}
qquad
begin{tabular}{|l|l|}
hline
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
The problem with clist_map_inline:nn
is that it leaves TeX in the state where a new cell has already been started when it realizes that the loop has ended.
This is actually what clist_map_inline:nn
does: it defines a new “unnamed” function and does clist_map_function:nN
with it. However it also has to cover its tracks, particularly for being usable also nested, and for this it uses a counter that has to be stepped down at the end: this is the operation that creates the unwanted additional row.
More explicitly: clist_map_inline:nn { <clist> } { <code> }
roughly does
int_incr:Nn <reserved>_int
cs_gset:cn { <reserved> int_eval:n <reserved>_int :n } { <code> }
clist_map_function:nc { <clist> } { <reserved> int_eval:n <reserved>_int :n }
int_decr:Nn <reserved>_int
The function passed to clist_map_function:nc
so depends on the nesting level, because the reserved counter is associated to clist mappings. This allows clist_map_inline:nn
to contain in its second argument an inner clist_map_inline:nn
, which will execute clist_map_function:nc
with a different function.
However, the int_decr:Nn <reserved>_int
operation will trigger, in your case, TeX starting a new cell. TeX tables are always rebellious beasts. ;-)
.
With the proposed definition, the operations on counters are skipped; of course you cannot nest clistMap
in clistMap
.
You need to use clist_map_function:nN
, defining a temporary function:
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{clistMap}{mm}
{
cs_gset:Nn __beelzebielsk_map:n { #2 }
clist_map_function:nN { #1 } __beelzebielsk_map:n
}
ExplSyntaxOff
begin{document}
begin{tabular}{|l|l|}
hline
clistMap{one, two, three}{#1 &\hline}
end{tabular}
qquad
begin{tabular}{|l|l|}
hline
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
The problem with clist_map_inline:nn
is that it leaves TeX in the state where a new cell has already been started when it realizes that the loop has ended.
This is actually what clist_map_inline:nn
does: it defines a new “unnamed” function and does clist_map_function:nN
with it. However it also has to cover its tracks, particularly for being usable also nested, and for this it uses a counter that has to be stepped down at the end: this is the operation that creates the unwanted additional row.
More explicitly: clist_map_inline:nn { <clist> } { <code> }
roughly does
int_incr:Nn <reserved>_int
cs_gset:cn { <reserved> int_eval:n <reserved>_int :n } { <code> }
clist_map_function:nc { <clist> } { <reserved> int_eval:n <reserved>_int :n }
int_decr:Nn <reserved>_int
The function passed to clist_map_function:nc
so depends on the nesting level, because the reserved counter is associated to clist mappings. This allows clist_map_inline:nn
to contain in its second argument an inner clist_map_inline:nn
, which will execute clist_map_function:nc
with a different function.
However, the int_decr:Nn <reserved>_int
operation will trigger, in your case, TeX starting a new cell. TeX tables are always rebellious beasts. ;-)
.
With the proposed definition, the operations on counters are skipped; of course you cannot nest clistMap
in clistMap
.
edited Nov 28 at 22:54
answered Nov 28 at 21:53
egreg
702k8618733147
702k8618733147
Could you explain why there's this difference betweenclist_map_function:nN
andclist_map_inline:nn
? There's nothing obvious to me about why one would have to leave a little extra stuff after the loop and the other doesn't. A reference for my familiarity: I've used TeX for several years, and I've read a few chapters of the TeXBook. I still find TeX and all related things extremely obtuse (once I want to start creating things of my own). Overall, not that familiar with the internals, TeX primitives, nor with Latex3.
– Beelzebielsk
Nov 28 at 22:41
@Beelzebielsk I added some more explanations
– egreg
Nov 28 at 22:54
It is an interesting question if that could be avoided somehow in the inline versions (I guess that is the same with all other functions of that nature too). If not it might be something that is worth documenting
– Frank Mittelbach
Nov 30 at 10:51
@FrankMittelbach I'm curious as to how you'd document this. I doubt you'd just say, "Careful using it with tables!" since I get the feeling that this detail could affect the display of other things. However, if you just said something more general to the effect of "the inline variant leaves stuff after the last iteration", I wouldn't understand that this could affect table typesetting. I struggle with TeX and LaTeX because the connections between various things is not obvious, and I stumble haphazardly onto those connections by reading books and random stackexchange posts.
– Beelzebielsk
2 days ago
@FrankMittelbach To say this another way, if the documentation already said, "The inline variants leave other stuff after the last iteration," I'd have still posted this question.
– Beelzebielsk
2 days ago
|
show 1 more comment
Could you explain why there's this difference betweenclist_map_function:nN
andclist_map_inline:nn
? There's nothing obvious to me about why one would have to leave a little extra stuff after the loop and the other doesn't. A reference for my familiarity: I've used TeX for several years, and I've read a few chapters of the TeXBook. I still find TeX and all related things extremely obtuse (once I want to start creating things of my own). Overall, not that familiar with the internals, TeX primitives, nor with Latex3.
– Beelzebielsk
Nov 28 at 22:41
@Beelzebielsk I added some more explanations
– egreg
Nov 28 at 22:54
It is an interesting question if that could be avoided somehow in the inline versions (I guess that is the same with all other functions of that nature too). If not it might be something that is worth documenting
– Frank Mittelbach
Nov 30 at 10:51
@FrankMittelbach I'm curious as to how you'd document this. I doubt you'd just say, "Careful using it with tables!" since I get the feeling that this detail could affect the display of other things. However, if you just said something more general to the effect of "the inline variant leaves stuff after the last iteration", I wouldn't understand that this could affect table typesetting. I struggle with TeX and LaTeX because the connections between various things is not obvious, and I stumble haphazardly onto those connections by reading books and random stackexchange posts.
– Beelzebielsk
2 days ago
@FrankMittelbach To say this another way, if the documentation already said, "The inline variants leave other stuff after the last iteration," I'd have still posted this question.
– Beelzebielsk
2 days ago
Could you explain why there's this difference between
clist_map_function:nN
and clist_map_inline:nn
? There's nothing obvious to me about why one would have to leave a little extra stuff after the loop and the other doesn't. A reference for my familiarity: I've used TeX for several years, and I've read a few chapters of the TeXBook. I still find TeX and all related things extremely obtuse (once I want to start creating things of my own). Overall, not that familiar with the internals, TeX primitives, nor with Latex3.– Beelzebielsk
Nov 28 at 22:41
Could you explain why there's this difference between
clist_map_function:nN
and clist_map_inline:nn
? There's nothing obvious to me about why one would have to leave a little extra stuff after the loop and the other doesn't. A reference for my familiarity: I've used TeX for several years, and I've read a few chapters of the TeXBook. I still find TeX and all related things extremely obtuse (once I want to start creating things of my own). Overall, not that familiar with the internals, TeX primitives, nor with Latex3.– Beelzebielsk
Nov 28 at 22:41
@Beelzebielsk I added some more explanations
– egreg
Nov 28 at 22:54
@Beelzebielsk I added some more explanations
– egreg
Nov 28 at 22:54
It is an interesting question if that could be avoided somehow in the inline versions (I guess that is the same with all other functions of that nature too). If not it might be something that is worth documenting
– Frank Mittelbach
Nov 30 at 10:51
It is an interesting question if that could be avoided somehow in the inline versions (I guess that is the same with all other functions of that nature too). If not it might be something that is worth documenting
– Frank Mittelbach
Nov 30 at 10:51
@FrankMittelbach I'm curious as to how you'd document this. I doubt you'd just say, "Careful using it with tables!" since I get the feeling that this detail could affect the display of other things. However, if you just said something more general to the effect of "the inline variant leaves stuff after the last iteration", I wouldn't understand that this could affect table typesetting. I struggle with TeX and LaTeX because the connections between various things is not obvious, and I stumble haphazardly onto those connections by reading books and random stackexchange posts.
– Beelzebielsk
2 days ago
@FrankMittelbach I'm curious as to how you'd document this. I doubt you'd just say, "Careful using it with tables!" since I get the feeling that this detail could affect the display of other things. However, if you just said something more general to the effect of "the inline variant leaves stuff after the last iteration", I wouldn't understand that this could affect table typesetting. I struggle with TeX and LaTeX because the connections between various things is not obvious, and I stumble haphazardly onto those connections by reading books and random stackexchange posts.
– Beelzebielsk
2 days ago
@FrankMittelbach To say this another way, if the documentation already said, "The inline variants leave other stuff after the last iteration," I'd have still posted this question.
– Beelzebielsk
2 days ago
@FrankMittelbach To say this another way, if the documentation already said, "The inline variants leave other stuff after the last iteration," I'd have still posted this question.
– Beelzebielsk
2 days ago
|
show 1 more comment
up vote
3
down vote
I am sure everyone will forgive my somewhat off-topic answer, and this is just to provide an example illustrating @egreg explanations:
documentclass{article}
usepackage{xinttools}
begin{document}
begin{tabular}{|ll|}
hline
xintFor #1 in {one, two, three}:
{#1 &\hline}
end{tabular}
begin{tabular}{|ll|}
hline
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
Although xintFor
acts non-expandably, it is careful not to do anything "non vanishing by pure expansion" at its end. This allows it to not trigger accidentally a new row. This constraint does however have some limitation effect on the features of xintFor
(see the boxed "15.17 xintifForFirst, xintifForLast" comments in xint.pdf).
Notice that the xintFor
nests well.
A side remark here is about the strange "gaps" one sees (when magnifying) at the joining of horizontal and vertical lines in both (identical) tabulars: add usepackage{array}
to fix that.
It's actually not that off-topic. The main goal of this question was to automate the creation of tabular-style forms. This is another method toward that approach. Though, I'm preferring the LaTeX3 stuff.
– Beelzebielsk
Nov 30 at 0:44
add a comment |
up vote
3
down vote
I am sure everyone will forgive my somewhat off-topic answer, and this is just to provide an example illustrating @egreg explanations:
documentclass{article}
usepackage{xinttools}
begin{document}
begin{tabular}{|ll|}
hline
xintFor #1 in {one, two, three}:
{#1 &\hline}
end{tabular}
begin{tabular}{|ll|}
hline
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
Although xintFor
acts non-expandably, it is careful not to do anything "non vanishing by pure expansion" at its end. This allows it to not trigger accidentally a new row. This constraint does however have some limitation effect on the features of xintFor
(see the boxed "15.17 xintifForFirst, xintifForLast" comments in xint.pdf).
Notice that the xintFor
nests well.
A side remark here is about the strange "gaps" one sees (when magnifying) at the joining of horizontal and vertical lines in both (identical) tabulars: add usepackage{array}
to fix that.
It's actually not that off-topic. The main goal of this question was to automate the creation of tabular-style forms. This is another method toward that approach. Though, I'm preferring the LaTeX3 stuff.
– Beelzebielsk
Nov 30 at 0:44
add a comment |
up vote
3
down vote
up vote
3
down vote
I am sure everyone will forgive my somewhat off-topic answer, and this is just to provide an example illustrating @egreg explanations:
documentclass{article}
usepackage{xinttools}
begin{document}
begin{tabular}{|ll|}
hline
xintFor #1 in {one, two, three}:
{#1 &\hline}
end{tabular}
begin{tabular}{|ll|}
hline
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
Although xintFor
acts non-expandably, it is careful not to do anything "non vanishing by pure expansion" at its end. This allows it to not trigger accidentally a new row. This constraint does however have some limitation effect on the features of xintFor
(see the boxed "15.17 xintifForFirst, xintifForLast" comments in xint.pdf).
Notice that the xintFor
nests well.
A side remark here is about the strange "gaps" one sees (when magnifying) at the joining of horizontal and vertical lines in both (identical) tabulars: add usepackage{array}
to fix that.
I am sure everyone will forgive my somewhat off-topic answer, and this is just to provide an example illustrating @egreg explanations:
documentclass{article}
usepackage{xinttools}
begin{document}
begin{tabular}{|ll|}
hline
xintFor #1 in {one, two, three}:
{#1 &\hline}
end{tabular}
begin{tabular}{|ll|}
hline
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
Although xintFor
acts non-expandably, it is careful not to do anything "non vanishing by pure expansion" at its end. This allows it to not trigger accidentally a new row. This constraint does however have some limitation effect on the features of xintFor
(see the boxed "15.17 xintifForFirst, xintifForLast" comments in xint.pdf).
Notice that the xintFor
nests well.
A side remark here is about the strange "gaps" one sees (when magnifying) at the joining of horizontal and vertical lines in both (identical) tabulars: add usepackage{array}
to fix that.
answered Nov 29 at 22:40
jfbu
45.4k65145
45.4k65145
It's actually not that off-topic. The main goal of this question was to automate the creation of tabular-style forms. This is another method toward that approach. Though, I'm preferring the LaTeX3 stuff.
– Beelzebielsk
Nov 30 at 0:44
add a comment |
It's actually not that off-topic. The main goal of this question was to automate the creation of tabular-style forms. This is another method toward that approach. Though, I'm preferring the LaTeX3 stuff.
– Beelzebielsk
Nov 30 at 0:44
It's actually not that off-topic. The main goal of this question was to automate the creation of tabular-style forms. This is another method toward that approach. Though, I'm preferring the LaTeX3 stuff.
– Beelzebielsk
Nov 30 at 0:44
It's actually not that off-topic. The main goal of this question was to automate the creation of tabular-style forms. This is another method toward that approach. Though, I'm preferring the LaTeX3 stuff.
– Beelzebielsk
Nov 30 at 0:44
add a comment |
up vote
3
down vote
You could make the original function safe in this position by use of noalign
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
cs_new_eq:NN clistMap clist_map_inline:nn
ExplSyntaxOff
begin{document}
begin{tabular}{|ll|}
noalignbgroupclistMap{one, two, three}{egroup#1 &\hlinenoalignbgroup}egroup
end{tabular}
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
Yes, I noticed that, I was not referring to the actual item being scoped but only to the additional dealings ofclist_map_inline:nn
in-between (if any) and after the last iteration.
– jfbu
Nov 30 at 17:10
@jfbu ah OK I'd have to check what it's really doing (or you could ask Joseph in chat:-)
– David Carlisle
Nov 30 at 17:35
add a comment |
up vote
3
down vote
You could make the original function safe in this position by use of noalign
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
cs_new_eq:NN clistMap clist_map_inline:nn
ExplSyntaxOff
begin{document}
begin{tabular}{|ll|}
noalignbgroupclistMap{one, two, three}{egroup#1 &\hlinenoalignbgroup}egroup
end{tabular}
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
Yes, I noticed that, I was not referring to the actual item being scoped but only to the additional dealings ofclist_map_inline:nn
in-between (if any) and after the last iteration.
– jfbu
Nov 30 at 17:10
@jfbu ah OK I'd have to check what it's really doing (or you could ask Joseph in chat:-)
– David Carlisle
Nov 30 at 17:35
add a comment |
up vote
3
down vote
up vote
3
down vote
You could make the original function safe in this position by use of noalign
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
cs_new_eq:NN clistMap clist_map_inline:nn
ExplSyntaxOff
begin{document}
begin{tabular}{|ll|}
noalignbgroupclistMap{one, two, three}{egroup#1 &\hlinenoalignbgroup}egroup
end{tabular}
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
You could make the original function safe in this position by use of noalign
documentclass{article}
usepackage{expl3}
usepackage{xparse}
ExplSyntaxOn
cs_new_eq:NN clistMap clist_map_inline:nn
ExplSyntaxOff
begin{document}
begin{tabular}{|ll|}
noalignbgroupclistMap{one, two, three}{egroup#1 &\hlinenoalignbgroup}egroup
end{tabular}
begin{tabular}{|ll|}
one &\hline
two &\hline
three &\hline
end{tabular}
end{document}
answered Nov 30 at 14:28
David Carlisle
479k3811121845
479k3811121845
Yes, I noticed that, I was not referring to the actual item being scoped but only to the additional dealings ofclist_map_inline:nn
in-between (if any) and after the last iteration.
– jfbu
Nov 30 at 17:10
@jfbu ah OK I'd have to check what it's really doing (or you could ask Joseph in chat:-)
– David Carlisle
Nov 30 at 17:35
add a comment |
Yes, I noticed that, I was not referring to the actual item being scoped but only to the additional dealings ofclist_map_inline:nn
in-between (if any) and after the last iteration.
– jfbu
Nov 30 at 17:10
@jfbu ah OK I'd have to check what it's really doing (or you could ask Joseph in chat:-)
– David Carlisle
Nov 30 at 17:35
Yes, I noticed that, I was not referring to the actual item being scoped but only to the additional dealings of
clist_map_inline:nn
in-between (if any) and after the last iteration.– jfbu
Nov 30 at 17:10
Yes, I noticed that, I was not referring to the actual item being scoped but only to the additional dealings of
clist_map_inline:nn
in-between (if any) and after the last iteration.– jfbu
Nov 30 at 17:10
@jfbu ah OK I'd have to check what it's really doing (or you could ask Joseph in chat:-)
– David Carlisle
Nov 30 at 17:35
@jfbu ah OK I'd have to check what it's really doing (or you could ask Joseph in chat:-)
– David Carlisle
Nov 30 at 17:35
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f462260%2fprevent-newline-after-clist-map-inline%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
If you use
clist_map_function:nN
instead it works (don't ask me why, though :)– Phelype Oleinik
Nov 28 at 21:44
3
you do not have an extra
\
to see the effect just userelax
or{}
orhline
in your second table.– David Carlisle
Nov 28 at 21:45
2
clist_map_inline:nn
is not expandable and will leave something behind the last hline which create a new line.– Ulrike Fischer
Nov 28 at 21:47
1
in your first code block you have two tables which have different output, the first has a extra spurious row, but that is not because the l3 code generated an extra
\
, addrelax
beforeend{tabular}
to the second tabular then the two will produce the same output.– David Carlisle
Nov 28 at 22:21
1
@Beelzebielsk yes anything in that position will start a cell and so a row, an assignment like
refstepcounter
or justrelax
(which does nothing) the only things in that position that do not start a new row have to expand to nothing, like@empty
– David Carlisle
Nov 28 at 22:30