TransWikia.com

Checking if a macro is called on bare application of itself

TeX - LaTeX Asked on March 25, 2021

So I want to create a command setcol{A}{n} which should produce {A}^{[n]} when called like this I also want setcol{setcol{A}{n}}{m} to produce {A}^{[n][m]} rather than {A^{[n]}}^{[m]}.

But, and this is what blocks just simply redefining setcol when evaluated inside the macro setcol, I want setcol{(setcol{A}{n} + B)}{m} to evaluate to {({A}^{[n]}+B)}^{[m]}.

So, basically I need to check if the argument to setcol is a bare call to setcol and do something different in that case. How can I do that? I feel there must be some kind of check with ifx but I’m a bit fuzzy on that.

One Answer

You can achieve this by testing whether the argument contains exactly 3 braced groups or tokens and if so whether the first of those tokens is setcol. If that is the case output the special case, else use the normal output.

The following uses expl3 to achieve this (because it already contains everything we need for those tests).

documentclass[]{article}

ExplSyntaxOn
NewDocumentCommand setcol {m m}
  {
    bool_lazy_and:nnTF
      { int_compare_p:nNn { tl_count:n {#1} } = 3 }
      { tl_if_head_eq_meaning_p:nN {#1} setcol }
      {
        pgerdes_setcol_special:nnnn #1 {#2}
      }
      {
        pgerdes_setcol_normal:nn {#1} {#2}
      }
  }
cs_new:Npn pgerdes_setcol_special:nnnn #1 #2 #3 #4
  {
    {#2} sp { [#3] [#4] }
  }
cs_new:Npn pgerdes_setcol_normal:nn #1 #2
  {
    {#1} sp { [#2] }
  }
ExplSyntaxOff

begin{document}
$setcol{A}{n}$

$setcol{setcol{A}{n}}{m}$

$setcol{(setcol{A}{n} + B)}{m}$
end{document}

enter image description here


Since you already had the idea to use ifx, here is how I would've done it without expl3 (so this might be a bit more educational), the idea remains the same, test whether it's 3 tokens and the first one is setcol.

documentclass[]{article}

makeatletter
newcommandsetcol[1]
  {%
    setcol@ifthree{#1}
      {%
        setcol@special#1{#1}%
      }
      {%
        setcol@normal{#1}%
      }%
  }
newcommandsetcol@ifthree[1]
  {%
    ifnumnumexprsetcol@count#1setcol@stop=3
      expandafter@firstoftwo
    else
      expandafter@secondoftwo
    fi
  }
newcommandsetcol@count[1]
  {%
    ifxsetcol@stop#1%
    else
      expandafter+expandafter1expandaftersetcol@count
    fi
  }
newcommandsetcol@special[5]
  {%
    ifxsetcol#1%
      {#2}^{[#3][#5]}%
    else
      {#4}^{[#5]}%
    fi
  }
newcommandsetcol@normal[2]
  {%
    {#1}^{[#2]}%
  }
newcommand*setcol@stop{setcol@stop}
makeatother

begin{document}
$setcol{A}{n}$

$setcol{setcol{A}{n}}{m}$

$setcol{(setcol{A}{n} + B)}{m}$
end{document}

(output like above)

Correct answer by Skillmon on March 25, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP