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 wanted to construct a command, say \newlet, that I could use to do

\newlet\x\y

and/or

\newlet\x=\y

such that \x is unique (ie, not already in use).

Here we go

\protected\def\newlet#1{%
  \@ifnextchar={\@firstoftwo{\@newlet{#1}}}{\@newlet{#1}}%
}
\def\@newlet#1{\@ifdefinable{#1}\relax\let#1= }

% Obviously works:
\newlet\sptoken=\@sptoken

% Obviously fails:
\newlet\sptoken\@sptoken
share|improve this question
1  
Could I ask what the idea is here? It's quite possible to define a function \newlet which will carry out a check and which works with implicit spaces, but the optional = is a pain. –  Joseph Wright Feb 28 '12 at 19:39
    
This seems to be a limitation of \@ifnextchar. I really wanted to do \newlet\temp@sptoken\@sptoken and it failed. I then traced the problem to the fact that \@xifnch expects an explicit blank space. In essence can \@ifnextchar be modified to work in 'all' cases? –  Ahmed Musa Feb 28 '12 at 19:51
    
@AhmedMusa You could use amsmath's \new@ifnextchar, but then \newlet\x= \y would not work. –  egreg Feb 28 '12 at 20:44
    
@egreg: Thanks. I knew about Michael Downes' \new@ifnextchar in AMS packages, but as you have noted, \newlet\x= \y fails. –  Ahmed Musa Feb 28 '12 at 21:38
add comment

2 Answers

up vote 6 down vote accepted

Dealing with spaces in a general way is tricky. What you want here is a peek-ahead-and-remove function. This is available in LaTeX3 as \peek_meaning_remove:NTF, where I would use

\RequirePackage{expl3}
\ExplSyntaxOn
\cs_new_protected:Npn \newlet #1
  {
    \peek_meaning_remove:NTF =
      { \cs_new_eq:NN #1 }
      { \cs_new_eq:NN #1 }
  }
\ExplSyntaxOff
\makeatletter
\newlet\sptoken=\@sptoken

This can of course be 'written out' in primitives. Ignoring the need to be careful about & tokens (using an Appendix D trick), something like

\makeatletter
\protected\long\def\newlet#1{%
  \protected\def\@newlet@fcommon{%
    \ifdefined#1%
      \expandafter\ERROR
    \fi
    \let#1= 
  }%
  \let\@tempa= =%
  \futurelet\@let@token\@newlet
}
\protected\def\@newlet{%
  \ifx\@let@token\@tempa
    \expandafter\@newlet@true
  \else
    \expandafter\@newlet@fcommon
  \fi
}
\protected\def\@newlet@true{%
    \afterassignment\@newlet@fcommon
    \let\@temp@= %
}

will work (it's a simplified version of \peek_meaning_remove:NTF with the branches hard-coded). Notice in particular that the = is removed using a \let along with an \afterassignment to regain control, rather than using a parameter.

The basic idea here is not dis-similar to \@ifnextchar, but does not include the loop to remove spaces which the latter does. The LaTeX3 bundle provides both 'pre-packaged' (the equivalent to \@ifnextchar is `\peek_meaning_remove_spaces:NTF).

share|improve this answer
    
Thanks. But this fails for \def\z#1{\newlet\y#1}\z{ }=\z. –  Ahmed Musa Feb 28 '12 at 21:22
    
@AhmedMusa I'm not sure what you mean. In your example, \y is \let to a space, and only then to you have an =. As that is after \z, it ends up being typeset. –  Joseph Wright Feb 28 '12 at 21:36
    
I was referring to the need for space gobbling as LaTeX kernel's \@ifnextchar does. In \newlet\y<forced space>=\z, I would expect <forced space> to be gobbled first. Thanks. I will try a scheme by Donald Arseneau that I saw applied in a different context. –  Ahmed Musa Feb 29 '12 at 19:18
add comment

Here is a variation on Joseph Wright's idea:

\protected\long\def\newlet#1{%
  \def\@newlet##1{%
    \ifdefined#1%
      \@latex@error{Command '\string#1' already exists}\@ehc
    \fi
    \let#1=
  }%
  \futurelet\@let@token\@@newlet
}
\protected\def\@@newlet{%
  \ifx\@let@token=%
    \expandafter\@newlet
  \else
    \expandafter\@newlet\expandafter\relax
  \fi
}

But it still fails for

\def\z#1{\newlet\y#1}\z{ }=\z
share|improve this answer
add comment

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.