1

Sorry if the title is too big, but I didn't know how to express it as something specific, I try to generate new columns in a table using custom commands, for instance:

\documentclass{scrbook}
\usepackage[nomessages]{fp}
\usepackage{ifthen}
\usepackage{pgfplotstable}
\usepackage{pgfplots}

\newcommand{\newcoltest}[1]%my custom command
{
\ifthenelse{\isodd{#1}}
{\FPeval{\result}{clip(#1+1)}}
{\FPeval{\result}{clip(#1*3/2-1)}}
\result
}

\begin{document}

\pgfplotstableread{
T
1
2
3
4
5
6
7
8
9
10
}\loadedtable
\pgfplotstablecreatecol[
   create col/assign/.code={%
     \getthisrow{T}\vala
     \edef\newentry{\noexpand\newcoltest{\vala}}%
     \pgfkeyslet{/pgfplots/table/create col/next content}\newentry
   }%
]{Sa}{\loadedtable}
\pgfplotstabletypeset[string type]\loadedtable%critic line

\end{document}

the critic line is \pgfplotstabletypeset[string type]\loadedtable, which works only with string type, when I change to another type or even do not put anything, an error ocurrs.

I put \noexpand based on pgfplotstable: Use command when defining new column with create col/assign/.code?, since without this I think that my command is not recognized.

I also can't plot it using tikz, and I think this is related

2 Answers 2

1

Something like this?

\documentclass{scrbook}
\usepackage{xfp}
\usepackage{pgfplotstable}
\usepackage{pgfplots}

\newcommand{\newcoltest}[1]%my custom command
{%
\ifodd#1
\fpeval{trunc(#1+1)}%
\else
\fpeval{trunc(#1*3/2-1)}%
\fi
}

\begin{document}

\pgfplotstableread{
T
1
2
3
4
5
6
7
8
9
10
}\loadedtable
\pgfplotstablecreatecol[
   create col/assign/.code={%
     \getthisrow{T}\vala
     \edef\newentry{\noexpand\newcoltest{\vala}}%
     \pgfkeyslet{/pgfplots/table/create col/next content}\newentry
   }%
]{Sa}{\loadedtable}
\pgfplotstabletypeset\loadedtable%critic line

\end{document}

enter image description here

All I did was to make the stuff expandable by

  • going from fp to xfp, and
  • dropping ifthen in favor of a simple \ifodd.
3
  • yes! @Schrödinger's cat, thanks for your speed and simplicity, in general for these cases, should I avoid using ifthenelse?, I have some more complicated commands
    – 4lrdyD
    Jan 1, 2020 at 1:50
  • 1
    @4lrdyD Avoiding it in general may be a tough call but there are the built in \ifodd and \ifnum and \ifcase tests, which do not not require a package and are expandable. I personally do not use the ifthen package, but per se it is a nice package, I think. Happy New Year!
    – user194703
    Jan 1, 2020 at 1:54
  • I understand, I will try to handle that, thanks again and Happy New Year too!
    – 4lrdyD
    Jan 1, 2020 at 2:02
2

Your idea of using \noexpand seems good to me, but prevents expansion of:

  • the next token;

  • only once, i.e.: if your \newentry is subject to another \edef, the \noexpand won't be there anymore to prevent expansion of \newcoltest—I guess this must be the cause of your troubles here.

To counter the second point, LaTeX2e's \protected@edef and \protect mechanism uses a clever trick to make the protection reinstate itself every time it is used inside one of the dedicated macros \protected@edef, \protected@write, etc. But e-TeX and derived engines (including pdfTeX, LuaTeX and XeTeX) have the \protected primitive which is more powerful, because it protects macros even inside engine primitives such as \edef and \write, and doesn't require one to use \protect. You just need to declare a macro as \protected and voilà, it won't be expanded inside \edef, \write, etc.

xparse's \NewDocumentCommand macro (as opposed to \NewExpandableDocumentCommand) creates \protected macros, because that is generally the safest thing to do unless you really know your macro is expandable. You can very simply use \NewDocumentCommand to define \newcoltest in order to solve your problem, even keeping \ifthenelse, \FPeval or other “non-expandable stuff” inside the replacement text of \newcoltest. Of course, there is no need for \noexpand in this case, since \NewDocumentCommand defines engine-protected macros—as if you had used e-TeX's \protected primitive.

\documentclass{article}
\usepackage[nomessages]{fp}
\usepackage{ifthen}
\usepackage{pgfplotstable}
\usepackage{pgfplots}
\usepackage{xparse}

\ExplSyntaxOn % No spurious spaces this way!

\NewDocumentCommand \newcoltest { m }
  {
    \ifthenelse{\isodd{#1}}
      {\FPeval{\result}{clip(#1+1)}}
      {\FPeval{\result}{clip(#1*3/2-1)}}
    \result
  }

\ExplSyntaxOff

\begin{document}

\pgfplotstableread{
T
1
2
3
4
5
6
7
8
9
10
}\loadedtable
\pgfplotstablecreatecol[
   create col/assign/.code={%
     \getthisrow{T}\vala
     \edef\newentry{\newcoltest{\vala}}%
     \pgfkeyslet{/pgfplots/table/create col/next content}\newentry
   }%
]{Sa}{\loadedtable}
\pgfplotstabletypeset[string type]\loadedtable

\end{document}

enter image description here

Besides, since you were talking conditionals with @Schrödinger'scat, you might be interested in knowing that expl3 has powerful expandable conditionals, for instance \bool_if:nTF, \str_case:nnTF and all their variants (see interface3.pdf after reading expl3.pdf).

5
  • It may be an interesting option @frougon, but when I change the string type to another type as fixed, it stops working, I also need to graph it.
    – 4lrdyD
    Jan 1, 2020 at 21:24
  • 1
    @4lrdyD Right, I wrote this for the MWE, but this can be inappropriate for other uses. AFAIUI, the reason is that with my method, the actual cell contents for the Sa column look like \newcoltest{1}, \newcoltest{2}, \newcoltest{3}, etc., since \newcoltest doesn't expand inside \edef. It does expand when used in normal document flow, which is why the table can be typeset. But if other code (e.g., graphing) tries to look precisely into the cells, for instance to compute min. and max. values, it won't be able to see more than \newcoltest{1}, \newcoltest{2}, etc., precisely because
    – frougon
    Jan 1, 2020 at 21:55
  • 1
    ... \newcoltest doesn't expand inside \edef. OTOH, with @Schrödinger'scat's approach and expandable commands inside the replacement text of \newcoltest, the dynamically-created cells as stored by pgfplotstable contain the results of the expandable computations, which allows other “users” of the table data (graphing, etc.) to examine values.
    – frougon
    Jan 1, 2020 at 22:03
  • I omit the \noexpand in the @Schrödinger's cat's code based on what you say and it also works, you're right!
    – 4lrdyD
    Jan 1, 2020 at 23:36
  • 1
    @4lrdyD Good catch, sorry. I had forgotten @Schrödinger'scat had left the \noexpand in place when I wrote the previous comments, but this suggests you understood well what I meant. Bed time, now. :-)
    – frougon
    Jan 1, 2020 at 23:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.