4

I've extended myself too much, so the short question is:

Why can't I define macros with the tikzcdpackage as defined below? (right above the "Old Solution" section)


Description

I recently developed a notation for functors and it was tempting to use the tikzcd environment. However, the problem is that 1) The macro must have more than 9 entries (I found a solution here). 2) The spacing was pretty terrible.

I finded a solution using array and some rotations (the solution code will be at the end), but mostly it works fine.

Old solution output

But, when using big categories names or whatever, space between terms becomes way to strange and preety lame. Back to tikzcd, I've almost with some additional tricks (but mostly "fairier"):

\begin{tikzcd}[row sep={0.22em}, column sep={0.01em}]
    {F}: & {\boldsymbol{\mathscr C}} \arrow[rr] &\hspace{0.5cm}& {\boldsymbol{\mathscr D}}        &   \\
    & {X} \arrow[dd,"{\phi}"'] \arrow[rr, mapsto] & & {F(X)} \arrow[dd,"{F(\phi)}"'] & {x} \arrow[dd,mapsto]\\
    & \,                                         & &              &   \\ 
    & {Y} \arrow[rr,mapsto]                     & & {Y}         & {F(\phi)(x)}
\end{tikzcd}

Which produces:

enter image description here

Now the arrows adjust itself to each case. So im done and wanted to define that macro. Copying what I did in the old way, it should be:

%----------------
% Black Tex Magic
%----------------
% Provide a way to declare and renew a command in one command
\newcommand{\neworrenewcommand}[1]{\providecommand{#1}{}\renewcommand{#1}}

% Covariant functor \newcommand{\covfunctor}[9]{ \neworrenewcommand{\ccovfunctor}[2]{ \begin{tikzcd}[row sep={0.22em}, column sep={0.01em}] {#1}: & {#2} \arrow[rr] &\hspace{0.5cm} & {#3} & \ & {#4} \arrow[dd,"{#8}"'] \arrow[rr, mapsto] & & {#5} \arrow[dd,"{#9}"'] & {##1} \arrow[dd,mapsto]\ & , & & & \ & {#6} \arrow[rr,mapsto] & & {#7} & {##2} \end{tikzcd} } \ccovfunctor }

Well... nothing could be that simple in TeX: It compiles an error but it doesn't show me exactly what it is. So... what went wrong?

Old Solution

It uses the same \neworrenewcommand as above.

\usepackage{rotating}
\usepackage{scalerel}
\newcommand{\covfunctor}[9]{
    \neworrenewcommand{\ccovfunctor}[2]{
        \begin{array}{rcccc}
            {#1}: & \hphantom{{#8}} {#2} & \longrightarrow & {#3} &  \\
            &   \hphantom{{#8}} {#4}    &   \longmapsto   & {#5} & {##1}\\
            &  \begin{turn}{90}
                \ensuremath{\overset{\begin{turn}{270}
                            \scaleobj{0.7}{\ensuremath{{#8}}}
                    \end{turn}}{\longleftarrow}}
            \end{turn} &  & \begin{turn}{90}
                \ensuremath{\overset{\begin{turn}{270}
                            \scaleobj{0.7}{\ensuremath{{#9}}}
                    \end{turn}}{\longleftarrow}}
            \end{turn} \hphantom{\scaleobj{0.7}{{#9}}} & \begin{turn}{90}
                \reflectbox{\ensuremath{\longmapsto}}
            \end{turn}\\
            &  \hphantom{{#8}} {#6} & \longmapsto & {#7} & {##2}
        \end{array}
    }
    \ccovfunctor
}
Bernard
  • 271,350
  • 1
    A general remark: When you want a macro with more than 9 arguments, it’s usually better to use some kind of keyval syntax. – Gaussler Sep 05 '21 at 17:52
  • I agree with Gaussler. Although in this case, are you really using this as a function? Are you going to be having two or more of these, but with different entries? If not, it would just be easier to type the diagram instead of having a macro type the diagram. – Teepeemm Sep 05 '21 at 19:57

2 Answers2

5

Using eleven arguments is very error prone. I suggest a different approach with a more natural syntax “by column”. The idea is to store the column data and to pick the needed items when they're needed in the diagram.

\documentclass{article}
\usepackage{tikz-cd}

\ExplSyntaxOn

% the syntax will be by columns: % \describefunctor{F}{\mathcal{C},X,\phi,Y}{\mathcal{D},F(X),F(\phi),F(Y)}[x,F(\phi)(x)] % with the last column optional

\NewDocumentCommand{\describefunctor}{mmmo} { \IfNoValueTF{#4} { \bool_set_false:N \l__mezzovilla_three_bool \mezzovilla_functor:nnnn { #1 } { #2 } { #3 } { } } { \bool_set_true:N \l__mezzovilla_three_bool \mezzovilla_functor:nnnn { #1 } { #2 } { #3 } { #4 } } }

\clist_new:N \l__mezzovilla_functor_one_clist \clist_new:N \l__mezzovilla_functor_two_clist \clist_new:N \l__mezzovilla_functor_three_clist \bool_new:N \l__mezzovilla_three_bool

\cs_new_protected:Nn \mezzovilla_functor:nnnn { \clist_set:Nn \l__mezzovilla_functor_one_clist { #2 } \clist_set:Nn \l__mezzovilla_functor_two_clist { #3 } \clist_set:Nn \l__mezzovilla_functor_three_clist { #4 } \begin{tikzcd}[ampersand~replacement=&] #1\colon &[-3em] __mezzovilla_item:nn { one } { 1 } \arrow[r] & __mezzovilla_item:nn { two } { 1 } \bool_if:NT \l__mezzovilla_three_bool { &[-1.5em] } \[-1.5em] & __mezzovilla_item:nn { one } { 2 } \arrow[r,mapsto] \arrow[d,swap,"__mezzovilla_item:nn { one } { 3 }"] & __mezzovilla_item:nn { two } { 2 } \arrow[d,swap,"__mezzovilla_item:nn { two } { 3 }"] \bool_if:NT \l__mezzovilla_three_bool { & __mezzovilla_item:nn { three } { 1 } \arrow[d,mapsto] } \ & __mezzovilla_item:nn { one } { 3 } \arrow[r,mapsto] & __mezzovilla_item:nn { two } { 3 } \bool_if:NT \l__mezzovilla_three_bool { & __mezzovilla_item:nn { three } { 2 } } \end{tikzcd} }

\cs_new:Nn __mezzovilla_item:nn { \clist_item:cn { l__mezzovilla_functor_#1_clist } { #2 } }

\ExplSyntaxOff

\begin{document}

[ \describefunctor{F}{\mathcal{C},X,\phi,Y}{\mathcal{D},F(X),F(\phi),F(Y)}[x,F(\phi)(x)] ]

[ \describefunctor{F}{\mathcal{C},X,\phi,Y}{\mathcal{D},F(X),F(\phi),F(Y)} ]

\end{document}

enter image description here

egreg
  • 1,121,712
  • +1 because there’s always something to learn in your answers (even when mine is a copy-paste of your code in other post) – Luis Turcio Sep 07 '21 at 13:42
  • I really liked this approach, making it possible to omit the map of each funtor. Unfortunately, there was some error when I didn't include a name for the funtor image. I tried with ..., { }, ... and other "gambiarras" (no nice translation, kind of a trick) but it was unable to compile. I saved the alternative in the same way, thank you very much. – Gustavo Mezzovilla Sep 11 '21 at 15:05
4

I believe everything is in the link you posted and in your code. Note that &\hspace{0.5cm}& is not right, you should write &[1cm]& and it is not necessary an extra row, this space can be adjusted with \\[5mm].

\documentclass{article}
\usepackage{mathtools}
\usepackage{mathrsfs}
\usepackage{tikz-cd}

%This is a first attemp with only 7 arguments \newcommand{\funtordia}[7]{% \begin{tikzcd}[row sep={0.22em}, column sep={0.01em}, ampersand replacement=&] #1: & \mathscr{#2} \arrow[rr] &[1cm]& \mathscr{#3} & \ & #5 \arrow[d,"#4"'] \arrow[rr, mapsto] & & #1(#5) \arrow[d,"#1(#4)"'] & #7 \arrow[d,mapsto]\[5mm] & #6 \arrow[rr,mapsto] & & #1(#6) & #7\cdot #4 \end{tikzcd} }

%This is taken from the egreg's answer in the link you posted \ExplSyntaxOn \NewDocumentCommand{\NewWeirdCommand}{mm} {% #1 = command to define, #2 = replacement text \cs_new:Npn #1 ##1 { \tl_set:Nn \l__covfun_args_tl { ##1 } #2 } } \NewDocumentCommand{\Arg}{m} { \tl_item:Nn \l__covfun_args_tl { #1 } }

\tl_new:N \l__covfun_parse_args_tl \ExplSyntaxOff

\NewWeirdCommand{\covfunctor}{% \begin{tikzcd}[row sep={0.22em}, column sep={0.01em}, ampersand replacement=&] \Arg{1}: & \mathscr{\Arg{2}} \arrow[rr] &[1cm]& \mathscr{\Arg{3}} & \ & \Arg{5} \arrow[d,"\Arg{4}"'] \arrow[rr, mapsto] & & \Arg{8} \arrow[d,"\Arg{7}"'] & \Arg{10} \arrow[d,mapsto]\[5mm] & \Arg{6} \arrow[rr,mapsto] & & \Arg{9} & \Arg{11} \end{tikzcd} }

\begin{document}

\funtordia{G}{D}{C}{d}{D}{D'}{y}% \qquad% \covfunctor{{F}{A}{B}{a}{A}{A'}{b}{B}{B'}{x}{y}}

\end{document}

which generates the following enter image description here

Luis Turcio
  • 2,757