3

I'm getting a little tired of defining all my mathematical operators with \DeclareMathOperator. Also it is rarely useful to have them as a macro. On the contrary it sometimes leads to macro name collision (e.g. \span). So I came up with the following:

\documentclass{article}
\usepackage{amsmath}
\catcode`\¡=\active
\def¡#1!{\operatorname{#1}}
\begin{document}
    \[e^{ix} = ¡cos! x + i¡sin! x\]
\end{document}

I'd like to get rid of the ! at the end and maybe use \ifmmode, to allow ¡ in normal text. Is that possible? Are there other side effects of my definition I should be aware of?

11
  • \newcommand{\op}[1]{\operatorname{#1}}. However, I can't understand the point.
    – egreg
    Feb 8, 2014 at 18:11
  • @egreg: Then I would have to write braces around the name. I don't want to write more than if I had used \DeclareMathOperator.
    – bodo
    Feb 8, 2014 at 18:12
  • How can TeX know where to end the operator name?
    – egreg
    Feb 8, 2014 at 18:13
  • It does know it for all the usual commands that start with \ .
    – bodo
    Feb 8, 2014 at 18:14
  • 3
    You're starting from a false premise. It's good to have a macro for constructs that are frequently used, such as the name of functions.
    – egreg
    Feb 8, 2014 at 18:27

1 Answer 1

8

You are starting from a false premise: it's good to have macros for frequently used constructs and math operators such as “sine” and “log” are no exception.

If an operator appears only a few times, then what's wrong in using

\operatorname{foo}

for those few cases? If you don't want to type so much, then

\newcommand{\op}[1]{\operatorname{#1}}

would allow simply typing

\op{foo}

that requires just three keystrokes more than your proposed syntax.

It's quite difficult to have a safe routine for scanning a name in the same way TeX does for control sequences. The scanning of control sequence names is built-in, while you should do it character by character, storing them as you go until finding something that's not a letter.

There's another catch: your proposed character ¡ will definitely not work if the document is compiled under

\usepackage[utf8]{inputenc}

because in that case it is not a single character, but two: its UTF-8 representation is 0xC2A1. You could use `, instead.

\documentclass{article}
\usepackage{xparse,amsmath}

\ExplSyntaxOn
\tl_new:N \l__canaaerus_name_tl

\cs_new_protected:Npn \canaaerus_bq_mathop:
 {
  % clear the container
  \tl_clear:N \l__canaaerus_name_tl
  % start the recursion
  \canaaerus_absorb:
 }

\cs_new_protected:Npn \canaaerus_absorb:
 {
  \peek_catcode:NTF a
   {% if the next token is a letter absorb it
    \__canaaerus_absorb_next:n
   }
   {% otherwise produce the operator name
    \__canaaerus_deliver:
   }
 }

\cs_new_protected:Npn \__canaaerus_absorb_next:n #1
 {
  % add the next letter to the container
  \tl_put_right:Nn \l__canaaerus_name_tl { #1 }
  % restart the recursion
  \canaaerus_absorb:
 }

\cs_new_protected:Npn \__canaaerus_deliver:
 {
  % produce the operator name
  \operatorname{\l__canaaerus_name_tl}
 }

% define the active back quote
\group_begin:
\char_set_catcode_active:N `
\cs_gset_eq:NN ` \canaaerus_bq_mathop:
\group_end:
\ExplSyntaxOff

% make the backquote math active
\AtBeginDocument{\mathcode``=\string"8000 }

\begin{document}

$`cos(\alpha+\beta)-`sin x$

\end{document}

Highly inefficient, but working. Of course, syntax errors such as typing

`sinx

wouldn't be caught.

enter image description here

A different approach is to ease defining operators:

\documentclass{article}
\usepackage{xparse,amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\DeclareMathOperators}{m}
 {
  \keys_set:nn { canaaerus/mathop } { #1 }
 }

\keys_define:nn { canaaerus/mathop }
 {
  unknown .code:n = \canaaerus_defop:n { #1 }
 }

\cs_new_protected:Npn \canaaerus_defop:n #1
 {
  \cs_if_exist:cTF { \l_keys_key_tl }
   {
    \msg_error:nnx { canaaerus/mathop } { exist } { \exp_not:c { \l_keys_key_tl } }
   }
   {
    \tl_if_empty:nTF { #1 }
     {
      \cs_new:cpx { \l_keys_key_tl } { \exp_not:N \operatorname { \l_keys_key_tl } }
     }
     {
      \cs_new:cpx { \l_keys_key_tl } { \exp_not:N \operatorname { #1 } }
     }
   }
 }
\msg_new:nnnn { canaaerus/mathop } { exist }
 {
  #1 already~defined
 }
 {
  The~command~#1 already~exists,~ignored
 }
\cs_generate_variant:Nn \msg_error:nnn { nnx }
\ExplSyntaxOff

\DeclareMathOperators{
  Tor,
  Hom,
  Span=span,
  %span, % if uncommented it would raise an error
}

\begin{document}
$\Tor\quad\Hom\quad\Span$
\end{document}
10
  • Can I use your code for defining a \DeclareMathOperators command as is, in a personal .sty or .cla file. I as k this question because it begins with \NewDocumentCommand – and a .sty or .cls file isn't really compiled.
    – Bernard
    Feb 8, 2014 at 23:59
  • @Bernard You can put the code in a .sty file; just change \usepackage into \RequirePackage. Put there all from \RequirePackage to \ExplSyntaxOff
    – egreg
    Feb 9, 2014 at 0:19
  • Is it possible to get the character used (backtick or ¡) from a macro (e.g. an argument to a package)? I tried to place \expandafters but it wouldn’t work...
    – bodo
    Feb 9, 2014 at 14:29
  • 2
    @canaaerus \expandafter is not abracadabra; what precisely do you want to do?
    – egreg
    Feb 9, 2014 at 16:56
  • 1
    @cfr Yes, XeLaTeX and LuaLaTeX first transform UTF-8 multibyte combinations into single characters.
    – egreg
    Feb 9, 2014 at 20:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.