Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I want to write a command which makes a norm of a vector, with following syntax: \xnorm{v}.

I want the norm delimiters to adapt to the size of the expression contained in \xnorm{}, BUT I want also an optional argument allowing to set the delimiter size manually. The concept is like this:

\newcommand{\xnorm}[2][adapt]{\LeftDelim{#1}\|\, #2\, \RightDelim{#1}\|}

where \LeftDelim expands to \left if the first argument is not given by the user and expands e.g. to \Big if the user give \Big in the first argument. Command \RightDelim is analogous.

But, it is just an idea. The problems come when implementing it. My try was as below:

\newcommand{\StringA}{adapt}
\newcommand{\StringB}{aaaaa} % This is temporary definition only, because this command is required to be well-defined.
\newcommand{\LeftDelim}[1]
{
\renewcommand{\StringB}{#1}
\ifx\StringA\StringB
\left
\else
#1
\fi
}
\newcommand{\RightDelim}[1]
{
\renewcommand{\StringB}{#1}
\ifx\StringA\StringB
\right
\else
#1
\fi
}
\newcommand{\xnorm}[2][adapt]{\LeftDelim\noexpand#1\|\, #2\, \RightDelim\noexpand#1\|}

Having the above, I use \xnorm as follows:

\begin{document}
\begin{dislpmaymath}
\xnorm[\Big]{X} \xnorm{\int_0^T}
\end{displaymath}
\end{document}

Question:

The first use of \xnorm above works correct, but the second generates the result equivalent to adapt\|\int_0^T adapt\|. It seems that the comparison of \StringA and \StringB failed in my macros. On the other hand, code

\begin{displaymath}
\LeftDelim{adapt}\| {\int_0^T} \RightDelim{adapt}\|
\end{displaymath}

generates the expected result - an integral sign with big norm delimiters. Thus, perhaps the problem is with expanding the argument for \LeftDelim and \Rightdelim. But I cannot figure what exactly should be changed. I have been manipulating a lot with \expand and \expandafter commands, with no positive result.

share|improve this question
1  
Well, I think you should have a look at the macros \DeclarePairedDelimiter and \DeclarePairedDelimiterX of the package mathtools. Their purpose is exactly to create paired delimiters like your \xnorm. –  tohecz Dec 16 '13 at 14:52
    
Thanks, I will check it out. But I'm still interested in how to implement it by myself since I try to avoid extra packages. I believe that the solution isn't much more complex that the code snippet given in my question. –  Gregory Dec 16 '13 at 14:59
2  
Well, mathtools is, IMHO, an unavoidable package. Just see what all "math" "tools" it provides. Maybe you'll find that it would have saved you hours of complicated LaTeX coding if you knew that. –  tohecz Dec 16 '13 at 15:02

2 Answers 2

You don't want to use \left and \right by default. Really. You've been warned.

Now, the best thing you can do is to use mathtools and type

\usepackage{mathtools}
\DeclarePairedDelimiter{\xnorm}{\lvert}{\rvert}

so that you'll be able to use

$\xnorm{v}$       % not expanding version
$\xnorm[\big]{v}  % slightly bigger
$\xnorm[\Big]{v}  % bigger
$\xnorm[\bigg]{v} % even bigger
$\xnorm[\Bigg]{v} % quite enormous
$\xnorm*{v}$      % self-adapting (with \left and \right)

If you want to implement it yourself and the wrong way, that is, with automatic \left and \right (did I say it's a bad choice? Well, it is), here's how

\makeatletter
\newcommand{\xnorm}[2][]{%
   \if\relax\detokenize{#1}\relax
     \expandafter\@firstoftwo
   \else
     \expandafter\@secondoftwo
   \fi
   {\left|#2\right|}%
   {\mathopen{#1|}#2\mathclose{#1|}}%
}
\makeatother

and call as before, with the difference you have no * version any more.

A better choice would be using xparse, that allows also for specifying an empty optional argument (with the above macro it would result in using \left and \right):

\usepackage{xparse}
\NewDocumentCommand{\xnorm}{om}{%
  \IfNoValueTF{#1}
    {\left|#2\right|}
    {\mathopen{#1|}#2\mathclose{#1|}}%
}

But do yourself a favor and use \DeclarePairedDelimiter and add \left and \right only when they're really necessary. Did I already say it?

share|improve this answer
    
1. Ok, I have received the message - \left and \right are evil. But why? –  Gregory Dec 16 '13 at 16:08
    
2. The simplicity of \DeclarePaireDlimiter is appealing. But is mathtools that common package? Many journals require not using odd packages when submitting a paper. Isn't it risky to use it and later be forced to correct manually whole TeX file? –  Gregory Dec 16 '13 at 16:10
1  
@Gregory Compare $a\left|x\right|$ and $a\lvert x\rvert$. Journals that don't want extra package don't want personal macros either. –  egreg Dec 16 '13 at 16:12

Please always post complete documents not fragments that have to be assembled, the you could test your example and avoid \begin{dislpmaymath}

The initial error was that you were never passing #1 to your left and right macros you always passed the single token \noexpand

then in the case that you did not use \left and used #1 (\big) you passed \fi rather than the delimiter as the argument to \big so things go very wrong. You need \expandafter and you need the % otherwise the token after # is a space token not \fi.

Note that this fixes the errors but still uses \Big on left and right, you will get better spacing if you used \Bigl on the left and \Bigr on the right.

\documentclass{article}

\begin{document}


\newcommand{\StringA}{adapt}
\newcommand{\StringB}{aaaaa} % This is temporary definition only, because this command is required to be well-defined.
\newcommand{\LeftDelim}[1]
{
\renewcommand{\StringB}{#1}
\ifx\StringA\StringB
\left
\else
\expandafter#1%
\fi
}
\newcommand{\RightDelim}[1]
{%
\renewcommand{\StringB}{#1}%
\ifx\StringA\StringB
\right
\else
\expandafter#1%
\fi
}
\newcommand{\xnorm}[2][adapt]{\LeftDelim{#1}\|\, #2\, \RightDelim{#1}\|}


\begin{displaymath}
\xnorm[\Big]{X} \xnorm{\int_0^T}
\end{displaymath}
\end{document}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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