7

Out of curiosity I wanted to find the limits of TeX regarding macro definitions. Assume there should be an assignment command which assigns the value of an already defined macro to a yet undefined macro, so something like

\def\newVariable{\variable}

just with the syntax usually find in other languages, i.e. using the equal sign as an assignment operator.

I guess it's not possible to write

\newVariable = \variable

as this results in an 'Undefined control sequence' when \newVariable is read. Is it possible to hook into the execution of whatever detects the undefined control sequence and look ahead with @ifnextchars for an equal sign and an macro?

What were if we'd write

newVariable = \variable

Now this should at least run without error. When \variable is expanded, is there any chance to remove the text newVariable = from the output string again (do some sort of rewinding) and use it in \variable as an option similar to \variable{newVariable}? So I guess here I would look for something like \@iflastchars. I am all open for bizarre solutions with all TeX flavours like finding the string in the output routine or in the aux or even in the PDF file produced by the last run (or any of the other output files).

I guess the answer will be "this is not possible", but as there are a lot of smart people around liking a challenge, I thought I'd give it a try. Please note, that I am fully aware of the solution with the normal TeX syntax so this is a more a theoretical exercise.

  • When do you want \variable to be expanded? (It doesn't get expanded in \def\newVariable{\variable}.) – Ian Thompson Oct 08 '12 at 18:45
  • you can use = for assigment, you just have to use \let as well: \let\newVariable = \variable. You can use = for counters and lengths: \c@section = 5, \footskip = 5mm. However, in LaTeX, you better avoid these low-level format if you don't need them. You must think of (La)TeX as of a "different programming language" that has its very strange specifics ;) – yo' Oct 08 '12 at 18:47
  • @IanThompson Good point. I thought it would only be possible if \variable would be expanded after reading the equal sign, as otherwise there is no chance of changing the execution. If it gets expanded it could do whatever it wants to hide the expansion to the outside if that is wanted. If you find a solution without expansion that would also be great. – Patrick Häcker Oct 08 '12 at 18:54
  • @tohecz You are completely correct, thanks for the example. Interestingly this is possible either because a macro (ok, a primitive command) \let is left of the \newVariable (it's the same with \def) or because the thing is already defined (for counters and lengths). I guess my question could be reformulated as: Is this possible with yet undefined macros without having a macro like \let on the left? – Patrick Häcker Oct 08 '12 at 18:58
  • The problem is that you need to use = as a "text" and "math" character with its real meaning to the "normal" people. I think that doing this is impossible because TeX reads its input lineary and invokes an error on an unknown macro in the input sequence. – yo' Oct 08 '12 at 19:11
  • @tohecz I also thought about making = active, but beside the problems you mentioned, it would also be too late, as the newVariable would have already been read and we again would have the same problem as before. – Patrick Häcker Oct 08 '12 at 19:22
  • If TeX reads an undefined control sequence in a moment when it is expanding things, the error will be inevitable. TeX isn't very good at letting you hook into this kind of internal process (maybe LuaTeX is). There are however loads of programming languages where you can't just assign a new identifier without having declared it before. If you make a statement \declarevariable\variable you can define \variable such that later \variable={something} will execute the assignment. – Stephan Lehmke Oct 08 '12 at 19:35
  • @StephanLehmke Really interesting. So comparing it with a strongly dynamically typed language we would write something like \double \newVariable = \variable, where the \double command could take care of creating \newVariable and ensuring its type. This is fair enough, although there are languages which allow using a variable before declaring it (though this might indeed be a bad idea). – Patrick Häcker Oct 08 '12 at 19:44
  • Your initial question isn't very clear, Your description seems to suggest you are asking if \newVariable=\variable could be an alternative syntax to \let\newVariable=\variable but you give the example of being like \def\newVariable{\variable} which is a very different assignment. It is of course possible to do this if you make \ active but that then makes you incompatible with everything so you'd have to rewrite latex (or whatever other format you use). Most other macro language aslo need a define keyword not just an infix = think #define in C pre-processor . – David Carlisle Oct 08 '12 at 22:42
  • On using before declaring: Your example of using \variable in \def\newVariable{\variable} will work even before declaring \variable. Apart from theoretical musings, I'd like to point out that setting this kind of thing into action needs really deep knowledge of the inner workings of TeXs macro processing. If you `just' want to use TeX productively, then it would be much better to acquire a better understanding of the way things are supposed to be instead of trying to turn TeX into another language. – Stephan Lehmke Oct 09 '12 at 03:28
  • @DavidCarlisle You are right about my mixture of \let and \def. I just had the case of defining basically a primitive constant and then it does not matter much which of both is used. – Patrick Häcker Oct 09 '12 at 19:18
  • @StephanLehmke Yes, the definition may appear before its definition, but not before its usage. Implicitly, I assumed, that a variable may be used directly after its defintion, so it does not matter for my use case, but thanks for highlighting, as I didn't write that explicitly. And don't be afraid, I won't use that productively and I do not recommend anyone to (mis-)use TeX like this. It was really just curiosity and learning new aspects of TeX (as e.g. egreg provided) – Patrick Häcker Oct 09 '12 at 19:24

2 Answers2

9

If TeX doesn't know the meaning of a control sequence, it will complain with Undefined control sequence, unless you are assigning a meaning to the control sequence itself.

So, no, there is no way to say something like

\varB=\varA

where \varB has no previous meaning. Anyway, a syntax like this is allowed only for registers (that have previously been declared or are primitive). So, for instance,

\tolerance=\mycount

is a legitimate assignment to the primitive register \tolerance, but only when \mycount is a register of the same type (in this case an integer), be it primitive or defined by \countdef, for instance

\countdef\mycount=123

(Such an assignment, that makes \mycount equivalent to the primitive register \count123, is usually performed behind the scene by the macro \newcount.)

If one says

\varB=\varA

where \varA has a meaning and \varB hasn't there will be an error, as said before. If \varB has a meaning and it is not compatible with the assignment, there will be again an error. For instance,

\newcount\varA \varA=42
\newdimen\varB
\varB=\varA

will throw the error Illegal unit of measure (pt inserted), unless, by chance, the following tokens may be interpreted as a legal unit of measure.

Conversely,

\newdimen\varA \varA=42pt
\newcount\varB
\varB=\varA

is legal and \varB will hold the integer 2752512 (the equivalent of 42pt in scaled points: 2752512 = 42 * 65536). This is because dimensions are stored internally as integers, but it's a rather esoteric topic.

Notice that

\newcount\varA \varA=42
\newcount\varB
\varB=\varA

is very different from

\newcount\varA \varA=42
\let\varB=\varA

In the first case, changing the value stored in \varA will not change the one stored in \varB, while in the second case it will, because \varB has become an alias for \varA.

Hooking into the mechanism that discovers undefined control sequences is not possible at the user's level and requires rewriting "TeX the program".

Of course it's theoretically possible to modify the syntax rules of TeX by declaring all characters active after having created a suitable set of macros; so, for instance, each letter might store itself somewhere waiting for some operator to come along telling what to do with the saved tokens. Say

newvariable = myvar ;

where the semicolon acts as "end of instruction". The active = would be defined as "look at what comes until the semicolon, determine its type and perform the assignment to the variable whose name results from the tokens in the storage bin". There are papers by Jonathan Fine on TUGboat describing this sort of plays, see for instance "Active TeX and the DOT Input Syntax" (TUGboat, v. 20, n.3, p. 248–254). Nothing is really impossible, the problem is: is it worth the labor? Of course one must define a "programming environment" and a "typesetting environment", since, after all, TeX's job is primarily typesetting documents.

egreg
  • 1,121,712
  • Very informative, thanks! Any thoughts about using arguments left of the macro, i.e. some sort of postfix notation? – Patrick Häcker Oct 08 '12 at 19:34
  • @MMM No chance: TeX works on the first token it finds. Don't forget that its primary job is to typeset text, so if it finds an A it typesets it and doesn't look ahead to see if something comes along to which this A should be passed as an argument. – egreg Oct 08 '12 at 19:44
  • So if even you do not see a chance, this might really be impossible. Anyway, as mentioned to tohecz, I will wait until tomorrow to see if there is really no brilliant/insane solution to this artificial problem. – Patrick Häcker Oct 08 '12 at 19:50
  • Well, there's one very theoretical way, and that is, making \ an active character. But it would be so screwed and probably kill many other things. – yo' Oct 08 '12 at 20:25
  • @MMM I've added some comments about some possible (devious) ways to proceed. – egreg Oct 08 '12 at 20:27
4

No, it is not possible to make TeX do some action on finding an undefined sequence, other than invoking an error. TeX core reads the input sequence lineary, so no command can really influence what was read before. Moreover, the chracter = needs to be used in other contexts as well so it cannot easily be made active.

As I point out in the comments, there are cases where = means assignment:

  • \let definition: \let\newmacro=\oldmacro
  • Lengths assignment: \topskip = 10pt
  • Counter assignment: \c@section = 5
yo'
  • 51,322
  • You have good arguments, that's why I upvoted. Nevertheless, I will wait with accepting, because I will regard this as impossible after it is either proven or if nobody found a solution in the next 24 hours. – Patrick Häcker Oct 08 '12 at 19:26
  • 2
    of course arguably in all your examples, = means nothing rather than means assignment, as the meaning of the expression would be the same without the = : \c@section = 5 is just syntactic sugar for \c@section5 – David Carlisle Oct 08 '12 at 23:04
  • @DavidCarlisle unless you're wanting to be bullet-proof where you should use = with let, in the case when \oldmacro is = itself. – yo' Oct 10 '12 at 08:30
  • well yes but if you are paranoid then you'd also want to handle a space token as well space before or after the equals is ignored usually) – David Carlisle Oct 10 '12 at 08:37
  • And well, D. Knuth obviously did not choose = by mistake. Imagine if it had been \let\oldmacro!\newmaco, it would have been so confusing! So he clearly used = to stress that it is an assignment. – yo' Oct 10 '12 at 08:42