xiaofei@ACSU.BUFFALO.EDU (02/17/91)
If I say `` \the\baselineskip \baselineskip=2.0\baselineskip \the\baselineskip '' I expect the first \the\baselineskip gives me a ``12.0pt'' and the second one goves me a ``24.0pt''. But it is not the case, they both give me ``12.0pt'' which I find it difficult to understand. In order to get the results I expected I have to put \par in the first sentence. But this does not make sense to me. The value for \baselineskip HAS BEEN CHANGED regardless if there is a baselineskip. I expect the basic logic to work: `` x=1 means x is one x=2\times x then x is two obviously '' What is wrong with the way I am thinking?
X066TR@TAMVM1.BITNET ("Thomas J. Reid") (02/17/91)
On Sun, 17 Feb 91 03:05:17 EST xiaofei@acsu.buffalo.edu said: >If I say >`` >\the\baselineskip >\baselineskip=2.0\baselineskip >\the\baselineskip >'' > >I expect the first \the\baselineskip gives me a ``12.0pt'' and the >second one goves me a ``24.0pt''. But it is not the case, they both >give me ``12.0pt'' which I find it difficult to understand. The point which you are not understanding is the difference between TeX's parsing tokens, and executing commands. TeX processes the sequence by first expanding "\the\baselineskip" into its current value of "12.0pt". It then begins parsing the tokens "\baselineskip", "=", "2", ".", "0", "\baselineskip". At this point, TeX does not yet realize that it has a complete command which it can execute, so it continues parsing. It then finds "\the" which causes it to immediately expand the "\baselineskip" which follows it. This generates a new set of tokens: "1", "2", ".", "0", "p", and "t" which TeX stacks. Finally, TeX executes the assignment command and changes the value of \baselineskip to 24pt. Thus, it is the look-ahead action of the token parser which is causing your problem. To work around this problem, it is merely necessary to insert a token between the assignment and the second expansion of \the\baselineskip to cause TeX to actually make the assignment. Your test of inserting \par at this point would do the trick; however, if you didn't want a paragraph break there, it would have a bad side-effect. The best thing to do is to insert \relax after the assignment. The processing of dimensional arguments is one of the more confused aspects of TeX but is better understood when one realizes the two phases of parsing tokens and actually processing the commands. Regards, Tom Reid
eijkhout@s41.csrd.uiuc.edu (Victor Eijkhout) (02/18/91)
xiaofei@ACSU.BUFFALO.EDU writes: >What is wrong with the way I am thinking? Dunno, but let's think like TeX: >\the\baselineskip No problem. Print 12.0pt >\baselineskip=2.0\baselineskip Ha! We're doing a <glue> assignment. Lessee... The right hand side can be a glue parameter (e.g. \parskip), no that's not the case, it starts with 2.0. So maybe it's a glue denotation: <dimen> plus <fildimen> minus <fildimen> ^ optional ^ optional First 2.0/baselineskip. That's a <dimen> all right (note (this is me, VE, talking) that if \baselineskip=12pt plus 1pt, then 2.0\baselineskip is just 12pt, because it's a <dimen>; back to TeX:) now let's see if there's a `plus' or `minus' spec after this. >\the\baselineskip Hm ... `\the' ... I can expand that. Let's see what comes out. No. This just prints 12.0pt. Does not look like a `plus' or `minus'. Pity. I'll just assign the 2.0\baselineskip. So far \TeX. Now if you'd written once more \the\baselineskip, you would have gotten 24.0pt. The second one was just printed too early. Victor.
barr@TRIPLES.MATH.MCGILL.CA (Michael Barr) (02/18/91)
Indeed if you run the code: \the\baselineskip \baselineskip=2.0\baselineskip \the\baselineskip \bye through tex, the output is 12.0pt12.0pt If you run the code \the\baselineskip \baselineskip=2.0\baselineskip{} \the\baselineskip \bye through tex, the output is 12.0pt 24.0pt If you run \the\baselineskip \baselineskip=2.0\baselineskip\relax \the\baselineskip \bye the output 12.0pt24.0pt What is going on here is one of the most pernicious gotcha's in tex. The fact is that when tex reads a numerical quantity (and dimensions are also stored as numbers, in terms of sp's), tex has to read far enough to ascertain that the number has actually finished. If it discovers that the number actually finished a while back, it does not go back and reread what has already been read. In the first case, it read the \baselineskip=2.0\baselineskip and then continued past the carriage return (which was swallowed by the control sequence) to read the second \the, which apparently caused it to read the \baselineskip and then executed the code that it had absorbed. At that point, the value of \baselineskip was indeed 24.0pt, but what printed was the value when it was read. For some reason, it doesn't do this if instead of \the you execute \showthe\baselineskip. I don't understand why the two behave differently; I can only assume one takes place in the stomach and the other in the esophagous, or something like that. TeX's digestive tract is something of a black hole, at least to me. The remaining two contain a pair of braces or a \relax, both of which signal TeX that the dimension it is examining has ended and so it doesn't continue to read on. LaTeX has \relax inserted at various dates in strategic places, almost surely to forestall unexpected occurrences like this when a macro appears in a place not anticipated at the time it was originally coded. If you insert the pair of braces, the carriage return isn't swallowed and you get a space in there; with relax, you don't get the space. Michael Barr
X066TR@TAMVM1.BITNET ("Thomas J. Reid") (02/18/91)
On Sun, 17 Feb 91 16:48:31 EST Michael Barr said: > ... For some reason, it doesn't do this if instead of \the you >execute \showthe\baselineskip. I don't understand why the two behave >differently; I can only assume one takes place in the stomach and the >other in the esophagous, or something like that. TeX's digestive tract >is something of a black hole, at least to me. Michael, You must have tried the same thing I did when I saw the first note: run TeX substituting \showthe for \the. I noticed the same thing you did, but did not think anything of it at the time. After getting your note, I studied the problem again. It turns out that \the and \showthe are getting processed in different parts of TeX's "digestive tract"; \the in its "mouth," and \showthe in its "stomach." This explains why the two are different. The original poster asked me off-list for a pointers on understanding when and where expansions take place. The best place that I've found in _The_TeXbook_ is on page 373: "TeX's control sequences are divided into two main categories, 'expandable' and 'unexpandable'; the former category includes all macros and \if...\fi tests, as well as special operations like \the and \input, while the latter category includes the primitive commands listed in Chapter 24. The expansion of expandable tokens takes place in TeX's 'mouth,' but primitive commands (including assignments) are done in TeX's 'stomach.'" The \showthe primitive is among those listed in Chapter 24 (on page 279). ---Tom Reid
MJD@MATH.AMS.COM (Michael Downes) (02/18/91)
I don't think anyone has yet pointed out explicitly that in the combination \the\baselineskip \baselineskip=2.0\baselineskip \the\baselineskip TeX is looking ahead after the second line to see if "plus" or "minus" is coming up next. If you were to say \toks0={plus 3pt minus 1pt} and add a line saying \the\toks0\relax before the second \the\baselineskip, then you would find TeX reporting 24.0pt plus 3.0pt minus 1.0pt as the new value of \baselineskip; TeX would expand \the\toks0, and find some valid additions to the baselineskip assignment currently in progress, and therefore concatenate them to the assignment. Note that in the assignment statement \parskip=\baselineskip TeX would not look ahead for a "plus" or "minus" key word. In a direct skip register to skip register assignment the stretch and shrink of the right-hand register are taken as the "plus" and "minus" components and therefore TeX looks no further. *However*, any multiplier (such as 2.0) coerces a skip register to a dimension (see the TeXbook, answer to exercise 24.3), and then the stretch and shrink of the right-hand skip register are ignored; that's why TeX looks further. If you wrote instead \multiply\baselineskip by 2 the coercion would not take place. However, since \multiply only works with integers, this wouldn't allow you to specify baselineskip factors of 1.7 or whatever, except by using \multiply and \divide statements to get the rational equivalent of the desired decimal. TeX's rules for calculating with numbers and dimensions are certainly idiosyncratic, but what seems to be rarely realized is that Knuth was working under two significant constraints that are unique to TeX: (1) the programming and the data are symbiotic; therefore you have to worry about distinguishing arithmetic fragments that should be executed and ones that should be typeset. (2) One of Knuth's goals was to make TeX as small and fast as possible, so that it could be made to work on as many machines as possible, even less powerful ones. He could probably have added a full-fledged arithmetic parser that would handle everything nicely, but then it might have taken until 1990 instead of 1984 for TeX to run on XT and AT-class machines, because of the larger program size. And/or run slower because of the virtual memory swapping operations involved. Knuth only implemented the minimum set of arithmetic operations that allowed him to do what he wanted. Michael Downes mjd@math.ams.com (Internet) -------