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 have already seen the related page macros - What is the difference between \let and \edef?, but I'm afraid it still doesn't expain to me the following MWE:

\documentclass{minimal}

\begin{document}

\let\tmpa=Hello
\edef\tmpb{A\tmpa}
\tmpb           % typesets "ello AH"
\typeout{\tmpa} % writes "\tmpa" in terminal
\typeout{\tmpb} % writes "A\tmpa" in terminal
\end{document}

This is how I understand it:

  • \let\tmpa= sees first character of Hello, H - it sees it as a single token and gets assigned to it (that is, \let\tmpa=H)
  • The remaining characters ("ello") from \let\tmpa=Hello "fall through" and get typeset (the "ello" in "ello AH")
  • \edef\tmpb{A\tmpa} runs => since \tmpa=H, then \tmpb should expand to "AH"
  • \tmpb runs => as expected, "AH" is typesed after the previous "ello"

And the confusion comes from \typeout{\tmpa} - from the typeset output, I'm pretty sure \tmpa=H; so I expect \typeout{\tmpa} to result with H, but it doesn't - and instead it writes again \tmpa! Same thing if I try to expand it via \edef and throw it in another command (\tmpb), and then I try to \typeout that command.

Why does \typeout in this case not show the "expanded" value of \tmpa? How can I get \typeout to show the expanded value of \tmpa?


Ah well, I asked this question; then I asked myself for it to be closed, given that Showing expanded \let command with \typeout generally provides an answer; in the meantime I came up with an answer I wanted to document - but now I cannot anymore, because it's closed :/ So I posted the answer in macros - How do I ‘expand’ a control sequence \let to a character?; but that answer simply doesn't belong there.

Then finally I realized I can edit my question post, even if it is closed (I just cannot add an answer) - so better to delete the answer from the other question, and move it here I guess (although now that it is here, it would have been better it's an answer :/ Ah nevermind).

So, not to nag the mods to reopen and reclose again, I'll post that answer here:

Basically, to \typeout the contents of that example:

  • Use \meaning to convert \tmpa to "The letter H"
  • Use a "parser" macro, to extract the third word from a set of three words

So finally we have the corrected MWE, that can print the content of \tmpa (given here we explicitly expect it to be one letter) to terminal:

\documentclass{minimal}

\begin{document}

\def\wordIIIofIII #1 #2 #3{#3}

\let\tmpa=Hello
\edef\tmpb{A\tmpa}
\tmpb           % typesets "ello AH"
\typeout{\tmpa} % writes "\tmpa" in terminal
\typeout{\tmpb} % writes "A\tmpa" in terminal

\edef\tmpc{\meaning\tmpa}
\typeout{\tmpc}         % writes "the letter H" in terminal
\edef\tmpd{\expandafter\wordIIIofIII\tmpc}
\typeout{\tmpd}         % writes "H" in terminal

\typeout{\the\catcode`H}                  % 11
% \typeout{\the\catcode`\tmpd} % "! Improper alphabetic constant."
\typeout{\the\catcode\expandafter`\tmpd}  %11

\end{document}
share|improve this question
1  
Keep in mind that \let must be followed by a control sequence (or an active character), an optional = and one token! Other tokens following the first won't belong to the \let instruction. –  egreg May 28 '12 at 8:33

1 Answer 1

up vote 4 down vote accepted

The syntax for the \let primitive is

\let<cs>=<token>

where <cs> is a control sequence or active character, <token> is a single token and = can be omitted or surrounded by optional spaces. So

\let\?=H
\let\? =H
\let\? = H
\let\?H
\let\? H

are all equivalent (I used \? so that no space is ignored in the tokenization stage).

The so defined <cs> inherits all the characteristics of the <token> (but depending on the token it may or may not be always used as a substitute). In particular, after

\let\tmpa=H

the token \tmpa will be unexpandable, just because H is unexpandable.

The command \typeout uses the \write mechanism, which does expansion, but using an output stream that is never assigned a file, so the result is written on the terminal and the log file, also adding an instruction so that \protect does its work correctly (for instance \typeout{\itshape} prints \itshape, while \write255{\itshape} would explode).

Under \write, unexpandable tokens are written by their name. And it's good it's this way: after \write\@outputstream{\bgroup}, finding out { in the output may be disastrous. Similarly one could have good reasons for writing out \tmpa instead of H.

The strategy with \meaning is correct, but it works only in this particular case and it would fail with \bgroup, whose meaning is

\bgroup=begin-group character {

You may find it useful to look at the expl3 package l3tl-analysis; compiling the following file

\RequirePackage{expl3,l3tl-analysis}
\let\tmpa=H

\ExplSyntaxOn
\tl_show_analysis:n { \tmpa }

will show on the terminal

The token list contains the tokens:
>  \tmpa (control sequence=the letter H).

Why isn't your \typeout{\the\catcode`\tmpd} working? Because an alphabetic constant is `<character> (where <character> may also be <backslash><character>) and after the backquote a multiletter control sequence is found, which is illegal.

The line \typeout{\the\catcode\expandafter`\tmpd} works, because \catcode expands tokens until finding something that can start a <number> (if not found, TeX raises an error). So the \expandafter is expanded.

share|improve this answer
    
Thanks for the answer, @egreg - didn't realize it was posted until now. Cheers! –  sdaau Jun 2 at 23:11

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.