4
\def\foo#1{a#1b}

creates \foo that expects for a mandatory argument when used.

I'm trying to create so called "anonymous" or "lambda" macro that is essentially a token list with a suspended expansion.

The idea is to have something like

{a#1b}{CCC}

which will output aCCCb.


My real use case is related to enumitem's format key

\documentclass{article}

\usepackage{enumitem}
\newcommand\mydesclabel[1]{\normalfont#1\quad ---}
\setlist[description]{format=\mydesclabel}

\begin{document}

\begin{description}
\item[A] foo
\item[B] bar
\end{description}

\end{document}

I want to avoid using \mydesclabel temporary macro and specify format directly.

I've tried so far:

\setlist[description]{format={\unexpanded{\normalfont#1\quad ---}}}
\setlist[description]{format={\aftergroup{\normalfont#1\quad ---}}}

Neither worked

5
  • That's just not possible, enumitem doesn't support this usage of format, you need a macro for that.
    – Skillmon
    Commented Jun 2 at 8:07
  • (La)TeX doesn't provide "anonymous" or "lambda" macros, unless a package specifically implements something along those lines.
    – Skillmon
    Commented Jun 2 at 8:09
  • @Skillmon consider titlesec. You can define format with \titleformat literally specifying #1 there and all that gets suspended for expansion and stored in a token list which is used later during all section creation. MWE: pastebin.com/f3XP5pxK, demo: imgur.com/a/GU9uvvk. So it should definitely be possible.
    – antshar
    Commented Jun 2 at 8:17
  • @antshar the #1 there is just a normal macro parameter there is no anonymous function involved, unless you mean that \titleformat itself is a macro definition which takes a name and a macro body using # which is of course the case, it is basically \def\ttl@format@si#1#2#3#4#5#6#7{% \@namedef{ttlf@\ttl@a}{#1{#7}{#3}{#4}{#5}{#6}}} Commented Jun 2 at 8:26
  • @antshar as David says, that's not an anonymous function. This concept just doesn't exist in TeX. Of course I can create an interface which expects you to input something as #1 (and many packages do so), but that's far from an anonymous function, that's just a frontend defining an internal macro.
    – Skillmon
    Commented Jun 2 at 17:00

2 Answers 2

5

enumitem uses its own key-value system, which is a bit of a nuisance. In particular, one cannot use #1 in the values for keys.

You could instead use \ARG (not a real command, but a placeholder for the specific case):

\documentclass{article}

\usepackage{enumitem}

\ExplSyntaxOn
\makeatletter
\enitkv@key{}{formatdef}{%
  \tl_set:Nn \l_tmpa_tl { #1 }
  \regex_replace_once:nnN {\c{ARG}}{\cP\#1} \l_tmpa_tl
  \exp_args:NNV \cs_set:Nn \enit_format:n \l_tmpa_tl
  \cs_set_eq:NN \enit@format \enit_format:n
}
\makeatother
\ExplSyntaxOff

\setlist[description]{formatdef={\normalfont\ARG\enspace---}}

\begin{document}

\begin{description}
\item[A] foo
\item[B] bar
\end{description}

\end{document}

enter image description here

2
  • Looks great. If regex replacement is used, it can treat everything as string, so why can't #1 be used instead of \ARG?
    – antshar
    Commented Jun 2 at 10:45
  • @antshar Because of how the setting of keys is defined in enumitem. If you use #1 this becomes the first argument to another internal macro. It's 0 in the particular case, but it could be 1 if description is at a different nesting level.
    – egreg
    Commented Jun 2 at 12:12
4

Internally for TeX to use the #1 parameter syntax there has to be a macro definition, however you can hide this from the user syntax (if you don't need an expandable function)

See how the LaTeX programming layer defines (say) \clist_map_function:NN which takes a named function in the second argument, or \clist_map_inline:Nn which takes an anonymous function body using #1 in the second argument.

Internally the inline version defines a temporary macro using the function body then maps that over the list.

A simple version of an an apply lambda function taking an anonymous function body, compared with an apply fun macro that takes a named function.

enter image description here

\documentclass{article}

\def\applyfun#1#2{#1{#2}}
\def\applylambda#1#2{\def\tmp##1{#1}\tmp{#2}}

\begin{document}

\def\fun#1{---\textbf{#1}---}

\applyfun\fun{abc1}

\applylambda{---\textbf{#1}---}{abc2}


\applylambda{---\textit{#1}---}{abc3}

\end{document}
2
  • \applylambda seem like a decent workaround. However, unfortunately \applylambda{...} doesn't work when passing to format=
    – antshar
    Commented Jun 2 at 10:42
  • 2
    @antshar well no but that is how you have to do anonymous function bodies in tex (all packages offering that are doing the internal def somewhere) the keyval system used by enumitem would need to be extended or probably simpler you could layer some front end so that you expand away the lambda before calling enumitem, but here I decided to stick to the core question of how to implement anonymous function bodies in tex. Commented Jun 2 at 10:45

You must log in to answer this question.

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