# How to get character code defined with \let (! Improper alphabetic constant)

Here's a example with the "! Improper alphabetic constant" error:

%% this is ok
\newcount\mychar
\mychar=\numbera\relax
\showthe a       % shows You can't use the letter a' after \the
\showthe\mychar  % shows 97

%% this is not ok
\let\Char=a
\showthe\Char    % shows You can't use the letter a' after \the
\mychar=\number\Char\relax  % here error comes
\showthe\mychar


Setting the counter should expand till non-expandable token (in this case it's \relax). Question: why is \Char not expanded?

\Char is not expanded because it is not an expandable token. Unlike \def\Char{a} which expands to a \let defines a token that essentially is a and like a it does not expand.

The only way to get hold of this in classic TeX is to take \meaning\Char which will be

the letter a


split that up on spaces, and if the first two words are the letter take the letter which will be a and then use the a syntax as you used.

Look at the source of the bm package which does a lot of this:-)

Working example (plain TeX)

\newcount\mychar

\def\zz#1{%
% catcode 11 (letter)
\ifcat a#1%
\expandafter\zza\meaning#1 \relax
\else
%other cases here
-1
\fi}

\def\zza#1 #2 #3 #4\relax{#3 }

\let\Char=a

\mychar=\zz{a}
\immediate\write20{a=\the\mychar}

\mychar=\zz{\Char}
\immediate\write20{\Char=\the\mychar}

\bye


which produces a log

a=97
\Char =97


showing the macro accepts explicit or implicit character tokens.

• I knew how to do it with meaning, just wanted to find a simpler solution :) Thanks I accept the answer. – Linuxss Dec 4 '13 at 12:17

Here's an implementation with l3regex; the number is stored in \l_linuxss_code_int for later usage.

One can extend the testing by acting on the search regular expression; this one catches the letter or the character.

\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand{\getlettercode}{m}
{
\linuxss_getlettercode:N #1
\int_to_arabic:n { \l_linuxss_code_int } % just for testing
}

\int_new:N \l_linuxss_code_int
\tl_new:N \l_linuxss_meaning_tl
\regex_const:Nn \c_linuxss_search_regex { \A the \s (letter|character) \s }

\cs_new_protected:Npn \linuxss_getlettercode:N #1
{
\tl_set:Nx \l_linuxss_meaning_tl { \token_to_meaning:N #1 }
\regex_match:NVTF \c_linuxss_search_regex \l_linuxss_meaning_tl
{
\regex_replace_once:NnN \c_linuxss_search_regex { } \l_linuxss_meaning_tl
\int_set:Nx \l_linuxss_code_int {  \l_linuxss_meaning_tl }
}
{
\int_set:Nn \l_linuxss_code_int { -1 }
}
}
\cs_generate_variant:Nn \regex_match:NnTF { NV }
\cs_generate_variant:Nn \int_set:Nn { Nx }
\ExplSyntaxOff

\begin{document}

\let\Chara=a
$\getlettercode{\Chara}=\numbera$

\let\Charz=z
$\getlettercode{\Charz}=\numberz$

\let\Charpipe=|
$\getlettercode{\Charpipe}=\number|$

$\getlettercode{\let}=-1$

\end{document}