12

I have read the question and answers about:

What I want to do is similar, but one step further. I would like to define a new command with a variable name, but the new command should have parameters (exactly one in my case).

I tried to use the hash symbol # twice, like this:

\newcommand{\deffun}[1]{\expandafter\newcommand[1]\csname #1\endcsname[1]{#1(##1)}}

But this does not seem to work and I am too confused or ignorant to produce a mwe with nesting of macro definitions with parameters. For an answer, pointing me to the relevant place of the documentation would be enough. It looks like nesting of macro definitions is not a commonly used nor explained feature.

PD: I was almost right, it is like this:

\newcommand{\deffun}[1]{\expandafter\newcommand\csname #1\endcsname[1]{#1(##1)}}
5
  • What is this \newcommand[1] supposed to do?
    – jon
    Sep 10, 2015 at 2:17
  • See also: tex.stackexchange.com/a/188478/8528 (shameless self-promotion; but examples are similar).
    – jon
    Sep 10, 2015 at 2:23
  • Use \def\deffun#1{\expadafter\def\csname#1\endcsname##1{#1(##1)}}. The combination of TeX primitives \csname, \endcsname with the LaTeX macro \newcommand looks funny. And pointer to the documentation? The TeXbook.
    – wipet
    Sep 10, 2015 at 3:37
  • @jon *facepalm* I'm sorry, I was getting errors and I thought that everything was wrong because (honestly) I had no idea of what I was doing. Turns out that was the only problem to make it work...
    – Trylks
    Sep 10, 2015 at 5:14

2 Answers 2

10

There are a number of ways to achieve this:

enter image description here

\documentclass{article}

\def\deffunA#1{\expandafter\def\csname #1\endcsname##1{#1(##1)}}

\newcommand{\deffunB}[1]{\expandafter\newcommand\csname #1\endcsname[1]{#1(##1)}}

\usepackage{etoolbox}
\newcommand{\deffunC}[1]{\csdef{#1}##1{#1(##1)}}

\begin{document}

\deffunA{abc}
$\abc{123}$

\deffunB{ghi}
$\ghi{123}$

\deffunC{jkl}
$\jkl{123}$

\end{document}

\deffunA uses a pure TeX way of defining a macro, while \deffunB is a LaTeX-related way of doing it. \deffunC uses etoolbox which provides a neat interface for defining macros. See section 3.1.1 Macro Definitions of the documentation. In fact, \csdef uses the LaTeX-defined \@namedef... yet another way of achieving what you're after.

3
  • Comprehensive, exhaustive and precise. Very good answer.
    – Trylks
    Sep 10, 2015 at 5:17
  • +1: Do you recommend one of the options over the others? Dec 22, 2019 at 13:59
  • 1
    @Dr.ManuelKuehner: Whichever makes sense to you. The hope would be that people understand the concept so they can expand/change it as needed.
    – Werner
    Dec 22, 2019 at 18:10
3

The error is in the wrong \newcommand[1].

Here's a way using expl3:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\deffun}{m}
 {
  \exp_args:Nc \newcommand{#1}[1]{#1(##1)}
 }
\ExplSyntaxOff

\begin{document}

\deffun{foo}

\texttt{\meaning\foo}

\end{document}

The output is

\long macro:#1->foo(#1)

The trick is that \exp_args:Nc jumps over the next token (N), takes the next braced group as an argument and makes a control sequence name out of it (c), and restarts from the jumped over token.

A possible “more proper” way, taking into account that the macro to be defined has just one parameter, would be

\NewDocumentCommand{\deffun}{m}
 {
  \cs_new:cpn {#1} ##1 { #1 ( ##1 ) }
 }

that essentially uses the same idea; note that \cs_new:... refuses to define an already existing command, but the definition is global (contrary to \newcommand).

Several variations are possible.

1
  • \cs_new:cpn {#1} { #1 ( ##1 ) } should be \cs_new:cpn {#1} ##1 { #1 ( ##1 ) }
    – cgnieder
    Sep 10, 2015 at 10:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .