5

I am trying to make a macro that defines a one-parameter macro for me (the reason is a veeeery long story). Here's my implementation.

\def\foo#1#2{%
\expandafter\def\csname bar#1\endcsname##1{#2}%
}

\foo{qix}{:: #1 ::}

\barqix{hi world}

Now the question. Using the #1 notation is possible but unaesthetic in my application. I would like use instead an unused macro, e.g. \PARAM . I guess for this I should be \leting \PARAM to #1, but something goes wrong if I do.

Any idea to get around this?

Werner
  • 603,163
Jaeya
  • 423
  • 2
    So you'd like \foo{qix}{:: \PARAM ::}? I find this much less aesthetic, besides giving a wealth of problems with space clobbering. – egreg Feb 24 '17 at 18:18

2 Answers2

4

Usually people have the opposite problem. ;-)

\def\PARAM{##1}
\def\foo#1#2{%
  \expandafter\edef\csname bar#1\endcsname##1{#2}%
}

\foo{qix}{:: \PARAM\space ::}

\barqix{hi world}

\bye

You have to use \edef, with all the connected problems, because TeX does no interpretation of the replacement text in a \def.

Otherwise, you'd have to do a lengthy scanning of the replacement text, substituting \PARAM with ##1; if it appears in a group…

Besides, I find

\foo{qix}{:: #1 ::}

much less clumsy.

Just for fun, with expl3 and l3regex:

\input expl3-generic

\ExplSyntaxOn
\cs_new_protected:Npn \foo #1 #2
 {
  \tl_set:Nn \l_tmpa_tl { #2 }
  \regex_replace_all:nnN { PARAM } { \cP\#1 } \l_tmpa_tl
  \cs_set:NV \temp:n \l_tmpa_tl
  \cs_set_eq:cN {bar#1} \temp:n
 }
\cs_generate_variant:Nn \cs_set:Nn { NV }
\ExplSyntaxOff

\foo{qix}{:: PARAM ::}

\barqix{hi world}

\bye
egreg
  • 1,121,712
3

You can do that by storing the captured argument in \PARAM. Note that parameterless macros gobble spaces after them, so you'll have to be careful in what you pass to the resulting macro:

enter image description here

\documentclass{article}

\begin{document}

\def\foo#1#2{%
  \expandafter\def\csname bar#1\endcsname##1{\def\PARAM{##1}#2}%
}

\foo{baz}{:: \PARAM ::}

\barbaz{hi world}

\foo{bat}{:: {\PARAM} ::}

\barbat{hi world}

\end{document}
Werner
  • 603,163
  • 1
    Well, if a call is nested… – egreg Feb 24 '17 at 18:28
  • 1
    @egreg: As in \barbat{hi \barbat{world}}? – Werner Feb 24 '17 at 18:29
  • 1
    For instance. If \PARAM is used twice, I foresee disaster. – egreg Feb 24 '17 at 18:31
  • This solution works, but as @egreg comments it might get very tricky if nested, which is precisely what I intended to do... – Jaeya Feb 24 '17 at 18:31
  • @Jaeya: It would be great if you can show examples of your use cases (which includes nesting). – Werner Feb 24 '17 at 18:33
  • I haven't yet writen one, but long story short: I am making an object-oriented engine and \PARAM is intended to be a sort of this in C++. When calling a destructor e.g. in a linked list, subsequent destructor calls will be issued. – Jaeya Feb 24 '17 at 18:35
  • I am actually unsure about how it will behave right now. I'll play with the idea and see if it would work. Thanks! – Jaeya Feb 24 '17 at 18:37
  • @Jaeya: You're better-suited to know what will work in your environment than me. You have two answers. If mine doesn't suit your needs, then try egreg's answer. If that doesn't work, provide more information. – Werner Feb 24 '17 at 18:39