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.

Why on earth does the following expression give me 0.0pt?

\edef\x{\the\dimexpr 3ex-1ex\relax}

I assume ex is a LaTeX unit, as it isn't in the TeXbook. Please where is it defined in the kernel?

EDIT

Many thanks for the answers. Ah, Joseph Wright had told me about \nullfont in my early days with TeX.

I was trying to complete the list {A_1ex,A_3ex,A_...,A_10ex} by using a scheme that is different from (and may be faster than) that used by \foreach. \foreach can't complete this list or {A_1pt,A_3pt,A_...,A_10pt}. The following usually fails:

\newcount\cnta
\cnta\z@
\foreach \p in {A_1pt,A_3pt,A_...,A_10pt}{%
  \global\advance\cnta\@ne
  \typeout{Doing \romannumeral\cnta=\p}%
}

I made the test in the package and hence \nullfont was in effect. I will remove font-dependent units from the permissible units, or make their use conditional on being in document body.

I said "may be faster" above because I have found that \foreach looks for ellipsis (...) in every element of the list, via:

\def\pgffor@scanned{%
  \ifx\pgffor@value\pgffor@stop
    \let\pgffor@next=\pgffor@after
  \else
    \expandafter\pgffor@dots@in@
      \pgffor@value\pgffor@dots@...\pgffor@dots@@\pgffor@stop
    \ifpgffor@dots@in@
      \let\pgffor@next=\pgffor@handledots
    \else
      \let\pgffor@next=\pgffor@handlevalue
    \fi
    <more>
}

EDIT

In the following definition in \foreach, two \relax are missing. Or is it deliberate? I don't think so.

\def\pgffor@makealphabetic#1{%
  \pgfutil@tempcnta=#1\relax%
  \ifnum\pgfutil@tempcnta>95\relax%
    \advance\pgfutil@tempcnta by-96%
    \expandafter\def\expandafter#1\expandafter%
    {\pgffor@alpha\pgfutil@tempcnta}%
  \else%
    \advance\pgfutil@tempcnta by-64%
    \expandafter\def\expandafter#1\expandafter%
    {\pgffor@Alpha\pgfutil@tempcnta}%
  \fi%
}

EDIT (2012/09/08)

In

{A_1ex, A_3ex, A_..., A_10ex}

my scheme recovers and uses ex (the original unit) in the completed/filled list. As percusse has pointed out, PGF's scheme requires

{A_1ex, A_3ex, A_...ex, A_10ex}

My scheme can also parse, e.g.,

{A_1pt-2bp*3+(3cc-2ex)/2, A_1pt-3bp*3+(3cc-2ex)/2, A_..., A_1pt-12bp*3+(3cc-2ex)/2}

but, because parsing this type of expression is expensive and unlikely to be passed by any user, I haven't included it in the relevant macros. I have retained it in the package as a future tool. What makes, e.g., 1pt-2bp*3+(3cc-2ex)/2 expensive to parse is the need to safely confirm that it is 'dimensionable'. A simple counter or dimension assignment will not always work in this case. I welcome some ideas in this regard.

One point: you can't reconstitute the syntax

1pt-2bp*3+(3cc-2ex)/2

after evaluation. Even PGF's scheme can't conceivably do it, for what are you going to put at the positon of X in

{A_1pt-3bp*3+(3cc-2ex)/2, A_1pt-9bp*3+(3cc-2ex)/2, A_...X, A_1pt-27bp*3+(3cc-2ex)/2}

There is not one unit (like pt or ex) to retain.

Maybe there is a need for something like

{A_1pt-3bp*3+(3cc-2ex)/2, A_1pt-9bp*3+(3cc-2ex)/2,
  A_...1pt-?bp*3+(3cc-2ex)/2, A_1pt-27bp*3+(3cc-2ex)/2}

Note ?. But won't that go ridiculously too far? TeX isn't theory.

share|improve this question
    
This \documentclass{article} \edef\x{\the\dimexpr 3ex-1ex\relax} \begin{document} \x \end{document} reports 8.61108pt. Am I missing something? –  Gonzalo Medina Sep 6 '12 at 3:53
3  
See Appendix F (page 433) of The TeXbook for \fontdimen5 and the values of 1ex (x-height). –  Gonzalo Medina Sep 6 '12 at 4:00
3  
@AhmedMusa Where exactly are you using this? Do you have a font loaded at the time, or is \nullfont active? –  Joseph Wright Sep 6 '12 at 6:11
    
It is in the TeXbook, with five mentions in the index. –  Stephan Lehmke Sep 6 '12 at 7:56
add comment

2 Answers

up vote 14 down vote accepted

The internal unit ex is explained in the TeXbook as follows:

ex is the "x-height" of the current font.

It is taken from \fontdimen5, as explained in Appendix F. So the value depends on the font.

\nullfont\edef\x{\the\dimexpr 3ex-1ex\relax}
\show\x

gives

> \x=macro:
->0.0pt.

If you use ex in LaTeX before \documentclass, you get 0pt as no font is selected at that time.

Also, there might be documentclasses (like minimal) where no font is selected even until \begin{document}!

Anyway, even if some font has been selected by \documentclass, you don't really know for sure which one, as the "real" initialisation of the document happens in \begin{document}.

So, be careful with font-dependent units like ex or em unless you know what the current font is!

(Thanks to Barbara Beeton for pointing out this problem!)

share|improve this answer
    
since the definition is in the preamble, no fonts are ordinarily selected before \begin{document}. that's why \nullfont is relevant (which isn't really clear to a newbie from the explanation as it now stands). –  barbara beeton Sep 6 '12 at 12:54
1  
@barbarabeeton What exactly do you mean? With \documentclass{article} \edef\x{\the\dimexpr 3ex-1ex\relax} \show\x I get 8.61108pt. –  Stephan Lehmke Sep 6 '12 at 13:03
    
@barbarabeeton Indeed the value is 0pt before \documentclass. I made an update. –  Stephan Lehmke Sep 6 '12 at 13:06
    
try it with \documentclass{minimal}. depends on the \documentclass, and that wasn't specified in the question. –  barbara beeton Sep 6 '12 at 13:07
    
@barbarabeeton You're right, of course. I tried to give some more helpful advice. –  Stephan Lehmke Sep 6 '12 at 13:15
add comment

\foreach can complete that list if you add ex or pt after the ellipsis. Example:

\documentclass{article}
\usepackage{pgffor}

\makeatletter
\newcount\cnta
\cnta\z@
\foreach \p in {A_1ex,A_2ex,A_...ex,A_10ex}{%
  \global\advance\cnta\@ne
  \typeout{Doing \romannumeral\cnta=\p}%
}


\begin{document}
.
\end{document}

Same applies to pt too.

enter image description here

share|improve this answer
    
Thanks, I didn't know that. That means the list completion scheme of \foreach is simpler than I had thought: the user has to give all the clues. I now have a scheme that takes {A_1ex,A_3ex,A_...,A_10ex}. And even {A_1ex,A_3ex,...,A_10ex}, with the key grow right or grow=right. But I have to revisit {A_1ex,A_3ex,A_...ex,A_10ex}, although the syntax is not something I like. –  Ahmed Musa Sep 6 '12 at 16:47
    
Oh I remember your solution from an earlier question. As my supervisor says a bit of ignorance helps to supersede the known ones. Probably, you wouldn't have that solution if this tip was available to you. :) –  percusse Sep 6 '12 at 16:50
    
I have looked at the \foreach code again. \foreach attempts to grow only numbers and characters, not dimensions or lengths. That is rather easy, but the use syntax seems (to me, anyway) to be weird. The dilemma I face is that if you simplify the use syntax, then internal parsing becomes more complicated. With {A_1ex,A_3ex,A_...,A_10ex}, my scheme assumes that everything on the right of _ is to be grown. With {A_1ex,A_3ex,...,A_10ex}, the user has to suggest link=_ and grow=right. But my scheme takes all sorts of list separators, even active parsers and subparsers. –  Ahmed Musa Sep 6 '12 at 17:14
    
Eg, \newforeach[parser=\do] \x:\y in {1:a\do 2:b\do 3:c}. \do may be used as a list processor in contexts outside \newforeach. The subparser : is detected automatically, but it can also be suggested by the user. –  Ahmed Musa Sep 6 '12 at 17:15
    
@AhmedMusa That's quite neat but then how would you avoid ambiguous entries such as {A_1ex2pt,A_3ex2pt,A_...,A_10ex2pt} would understand that it's just an appending 2 pt? (Not that it's relevant but suppose there are two disjoint number groups to the right for some reason) –  percusse Sep 6 '12 at 17:22
show 2 more comments

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.