1

I've learnt from this post how to swap two commands using the let primitive:

\let\temp\first
\let\first\second
\let\second\temp
\let\temp\undefined

Now, in order not to flood my preamble with this pattern, and to ease maintenance of my document, I wish to loop over this to perform all my swaps at once, with something like:

\foreach \lhs/\rhs in {%
    phi/varphi,%    easier to..
    sim/thicksim,%  .. tweak and maintain ..
    % ...           .. with a long list of swaps
    } {%
       % .. what to input here?
       % \expandafter\let\csname\lhs\endcsname\csname\rhs\endcsname 
       % does not work, because \let seems confined inside the loop scope
    }

How do I perform all my swaps in a row like this?
Why is there not an \xlet like there is a \xdef?

1

This works by parsing a comma separated list of \first/\second macros using listofitems. For the particular example, \swap{\phi/\varphi,\alpha/\beta}, this puts \phi into \swaplist[1,1] (after expanding twice the latter macro), \varphi into \swaplist[1,2], \alpha into \swaplist[2,1] and \beta into \swaplist[2,2].

Now all that is required is a loop through the first index (performed with \foreachitem) to do what the OP showed at the top...a series of \global\lets. The particulars are a game of expansion, so that the \swaplist macros are twice expanded at the time of the \let.

\documentclass{article}
\usepackage{listofitems}
\def\swapA{\let\temp}
\newcommand\swap[1]{%
  \setsepchar[-]{,-/}%
  \readlist*\swaplist{#1}%
  \foreachitem\x\in\swaplist{%
    \expandafter\expandafter\expandafter\swapA\swaplist[\xcnt,1]%
    \edef\swapB{\noexpand\global\noexpand\let\swaplist[\xcnt,1]}%
    \expandafter\expandafter\expandafter\swapB\swaplist[\xcnt,2]%
    \edef\swapC{\noexpand\global\noexpand\let\swaplist[\xcnt,2]}%
    \expandafter\swapC\temp%
  }%
}
\begin{document}
\swap{\phi/\varphi,\alpha/\beta}
\noindent phi: $\phi$\\
 varphi: $\varphi$\\
 alpha: $\alpha$\\
 beta: $\beta$
\end{document}

enter image description here

If the alternate syntax is desired, that omits the backslashes, \swap{phi/varphi,alpha/beta}, then this would suffice, to accomplish the same task. Double expansion is no longer needed, since \csname will fully expand its \swaplist argument.

\documentclass{article}
\usepackage{listofitems}
\def\swapA{\let\temp}
\newcommand\swap[1]{%
  \setsepchar[-]{,-/}%
  \readlist*\swaplist{#1}%
  \foreachitem\x\in\swaplist{%
    \expandafter\swapA\csname\swaplist[\xcnt,1]\endcsname%
    \edef\swapB{\noexpand\global\noexpand\let\csname\swaplist[\xcnt,1]\endcsname}%
    \expandafter\swapB\csname\swaplist[\xcnt,2]\endcsname%
    \edef\swapC{\noexpand\global\noexpand\let\csname\swaplist[\xcnt,2]\endcsname}%
    \expandafter\swapC\temp%
  }%
}
\begin{document}
\swap{phi/varphi,alpha/beta}
\noindent phi: $\phi$\\
 varphi: $\varphi$\\
 alpha: $\alpha$\\
 beta: $\beta$
\end{document}
| improve this answer | |
  • Wow. This seems to work indeed Ô.Ô What's the idea? Is the \foreach option a dead-end, and why? – iago-lito 'considering leaving Apr 16 '18 at 12:01
  • @iago-lito I added some commentary. – Steven B. Segletes Apr 16 '18 at 12:06
  • Well, cheers :) I'll have a look into this listofitems package, which seems quite powerful. Anyway, it looks like LaTeX remains quite hard to read and write for humans, right? XD – iago-lito 'considering leaving Apr 16 '18 at 12:09
  • @iago-lito I have added an alternate version, if you prefer the syntax without backslashes, \swap{phi/varphi,alpha/beta} – Steven B. Segletes Apr 16 '18 at 12:12
  • 1
    @iago-lito The listofitems package is extremely powerful and handy for dissecting complex lists. Documentation here: ctan.org/pkg/listofitems, and also search for listofitems on this tex.stackexchange website for ways it can be used. – Steven B. Segletes Apr 16 '18 at 12:16

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.