When to use edef, noexpand, and expandafter? Announcing the arrival of Valued Associate #679:...
The test team as an enemy of development? And how can this be avoided?
What did Turing mean when saying that "machines cannot give rise to surprises" is due to a fallacy?
Any stored/leased 737s that could substitute for grounded MAXs?
Is honorific speech ever used in the first person?
3D Masyu - A Die
Is there a verb for listening stealthily?
Searching extreme points of polyhedron
Vertical ranges of Column Plots in 12
As a dual citizen, my US passport will expire one day after traveling to the US. Will this work?
How can I prevent/balance waiting and turtling as a response to cooldown mechanics
Why are two-digit numbers in Jonathan Swift's "Gulliver's Travels" (1726) written in "German style"?
An isoperimetric-type inequality inside a cube
Inverse square law not accurate for non-point masses?
Is there a spell that can create a permanent fire?
Can two people see the same photon?
How does the body cool itself in a stillsuit?
Why did Bronn offer to be Tyrion Lannister's champion in trial by combat?
Does the main washing effect of soap come from foam?
Keep at all times, the minus sign above aligned with minus sign below
What is "Lambda" in Heston's original paper on stochastic volatility models?
How to ask rejected full-time candidates to apply to teach individual courses?
.bashrc alias for a command with fixed second parameter
One-one communication
What helicopter has the most rotor blades?
When to use edef, noexpand, and expandafter?
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)What are the differences between def, edef, gdef and xdef?How can I specify a long list of math operators?What is the difference between let and edef?How to properly smuggle (with or even without TikZ)?Does noexpand have to be a primitive?What does “expanding” mean in (La)TeX?How to understand and write LaTeX code?Re-using the title of the previous Beamer slideHow can I know the number of expandafters when appending to a csname macro?I'm a cargo cult programmer …Can one define an expandable command that removes control sequences from its argument?Why isn't everything expandable?Problem with nested noexpand and edefHow to redefine commands and environments, and make them acceptable for `write`How to use noexpand in an edef?How to expand a macro to use it inside a question in AMC?Expand a macro with parameters in tabular headDefine macro for sequence/list/tuple macrosInput command arguments from fileProtecting blocks of text and commands, not just one command, from expansion
I'm quite happy hacking TeX macros and cobbling together bits and pieces from different style files to suit my own ends, but I have a suspicion that my resulting hacks are not quite as elegant as they could be. In particular, with regard to when to expand and when not to expand macros.
A common occurrence for me is defining a meta-command that defines a whole slew of sub-commands. So the names of the sub-commands will contain parameters depending on the parameter passed to the meta-command, and the contents of the sub-commands will also vary a little depending on what the meta-command got. Often it won't be a direct substitution but rather a "if #1
is a
do this
else do that
", but this
and that
need expansion at define time, not call time.
Here's a very simple example just involving direct substitution:
defcohtheory#1{
expandafternewcommandexpandafter{csname #1funcendcsname}[1][*]{%
MakeUppercase{#1}^{##1}}
}
Sometimes I worry that my commands are more complicated than they need be. For example, if I want to call a command with two arguments and the arguments expand before the command, here's how I've coded it:
expandafter
expandafter
expandafter
commandexpandafter
expandafter
expandafter
{expandafter
argone
expandafter
}expandafter
{argtwo}
So I'm looking for guidance on when and how to control expansion in defining macros. I strongly suspect that such cannot be given in a simple answer, so to make this a focussed question, let me phrase it thus:
Where's a good reference for writing TeX macros that includes advice on how to best deal with how to handle expansions?
Of course, if anyone can formulate some advice in short answer, I'd be only to happy to read it.
(Note: this was partially motivated by juannavarroperez's adaptation of my answer to this question where over 20 expandafter
s got condensed down to just 1!)
macros tex-core expansion
add a comment |
I'm quite happy hacking TeX macros and cobbling together bits and pieces from different style files to suit my own ends, but I have a suspicion that my resulting hacks are not quite as elegant as they could be. In particular, with regard to when to expand and when not to expand macros.
A common occurrence for me is defining a meta-command that defines a whole slew of sub-commands. So the names of the sub-commands will contain parameters depending on the parameter passed to the meta-command, and the contents of the sub-commands will also vary a little depending on what the meta-command got. Often it won't be a direct substitution but rather a "if #1
is a
do this
else do that
", but this
and that
need expansion at define time, not call time.
Here's a very simple example just involving direct substitution:
defcohtheory#1{
expandafternewcommandexpandafter{csname #1funcendcsname}[1][*]{%
MakeUppercase{#1}^{##1}}
}
Sometimes I worry that my commands are more complicated than they need be. For example, if I want to call a command with two arguments and the arguments expand before the command, here's how I've coded it:
expandafter
expandafter
expandafter
commandexpandafter
expandafter
expandafter
{expandafter
argone
expandafter
}expandafter
{argtwo}
So I'm looking for guidance on when and how to control expansion in defining macros. I strongly suspect that such cannot be given in a simple answer, so to make this a focussed question, let me phrase it thus:
Where's a good reference for writing TeX macros that includes advice on how to best deal with how to handle expansions?
Of course, if anyone can formulate some advice in short answer, I'd be only to happy to read it.
(Note: this was partially motivated by juannavarroperez's adaptation of my answer to this question where over 20 expandafter
s got condensed down to just 1!)
macros tex-core expansion
26
That’s a typical example of cargo cult programming. I think I’m allowed to make this observation without being insulting since my TeX code looks exactly like this, i.e. I have the exact same problem. :-( All this to say that I was about to ask the exact same question.
– Konrad Rudolph
Jul 28 '10 at 10:54
4
Andrew, just because I saw your example above: I recently discovered the LaTeX2e macro@expandtwoargscommand{<arg1>}{<arg2>}
which expands the two arguments usingedef
before feeding it tocommand
.
– Martin Scharrer♦
Feb 15 '11 at 17:38
1
@MartinScharrer That's neat! Unfortunately, there does not seem to be an equivalent for three (or more?) parameters. :/
– Raphael
Nov 30 '12 at 14:18
3
@Raphael: Just look at the definition of@expandtwoargs
and define a macro for three arguments. Should not be any trouble.
– Martin Scharrer♦
Dec 1 '12 at 8:46
3
Relevant: A tutorial onexpandafter
– Werner
Oct 16 '15 at 23:34
add a comment |
I'm quite happy hacking TeX macros and cobbling together bits and pieces from different style files to suit my own ends, but I have a suspicion that my resulting hacks are not quite as elegant as they could be. In particular, with regard to when to expand and when not to expand macros.
A common occurrence for me is defining a meta-command that defines a whole slew of sub-commands. So the names of the sub-commands will contain parameters depending on the parameter passed to the meta-command, and the contents of the sub-commands will also vary a little depending on what the meta-command got. Often it won't be a direct substitution but rather a "if #1
is a
do this
else do that
", but this
and that
need expansion at define time, not call time.
Here's a very simple example just involving direct substitution:
defcohtheory#1{
expandafternewcommandexpandafter{csname #1funcendcsname}[1][*]{%
MakeUppercase{#1}^{##1}}
}
Sometimes I worry that my commands are more complicated than they need be. For example, if I want to call a command with two arguments and the arguments expand before the command, here's how I've coded it:
expandafter
expandafter
expandafter
commandexpandafter
expandafter
expandafter
{expandafter
argone
expandafter
}expandafter
{argtwo}
So I'm looking for guidance on when and how to control expansion in defining macros. I strongly suspect that such cannot be given in a simple answer, so to make this a focussed question, let me phrase it thus:
Where's a good reference for writing TeX macros that includes advice on how to best deal with how to handle expansions?
Of course, if anyone can formulate some advice in short answer, I'd be only to happy to read it.
(Note: this was partially motivated by juannavarroperez's adaptation of my answer to this question where over 20 expandafter
s got condensed down to just 1!)
macros tex-core expansion
I'm quite happy hacking TeX macros and cobbling together bits and pieces from different style files to suit my own ends, but I have a suspicion that my resulting hacks are not quite as elegant as they could be. In particular, with regard to when to expand and when not to expand macros.
A common occurrence for me is defining a meta-command that defines a whole slew of sub-commands. So the names of the sub-commands will contain parameters depending on the parameter passed to the meta-command, and the contents of the sub-commands will also vary a little depending on what the meta-command got. Often it won't be a direct substitution but rather a "if #1
is a
do this
else do that
", but this
and that
need expansion at define time, not call time.
Here's a very simple example just involving direct substitution:
defcohtheory#1{
expandafternewcommandexpandafter{csname #1funcendcsname}[1][*]{%
MakeUppercase{#1}^{##1}}
}
Sometimes I worry that my commands are more complicated than they need be. For example, if I want to call a command with two arguments and the arguments expand before the command, here's how I've coded it:
expandafter
expandafter
expandafter
commandexpandafter
expandafter
expandafter
{expandafter
argone
expandafter
}expandafter
{argtwo}
So I'm looking for guidance on when and how to control expansion in defining macros. I strongly suspect that such cannot be given in a simple answer, so to make this a focussed question, let me phrase it thus:
Where's a good reference for writing TeX macros that includes advice on how to best deal with how to handle expansions?
Of course, if anyone can formulate some advice in short answer, I'd be only to happy to read it.
(Note: this was partially motivated by juannavarroperez's adaptation of my answer to this question where over 20 expandafter
s got condensed down to just 1!)
macros tex-core expansion
macros tex-core expansion
edited Apr 13 '17 at 12:35
Community♦
1
1
asked Jul 28 '10 at 10:49
Loop SpaceLoop Space
113k30310610
113k30310610
26
That’s a typical example of cargo cult programming. I think I’m allowed to make this observation without being insulting since my TeX code looks exactly like this, i.e. I have the exact same problem. :-( All this to say that I was about to ask the exact same question.
– Konrad Rudolph
Jul 28 '10 at 10:54
4
Andrew, just because I saw your example above: I recently discovered the LaTeX2e macro@expandtwoargscommand{<arg1>}{<arg2>}
which expands the two arguments usingedef
before feeding it tocommand
.
– Martin Scharrer♦
Feb 15 '11 at 17:38
1
@MartinScharrer That's neat! Unfortunately, there does not seem to be an equivalent for three (or more?) parameters. :/
– Raphael
Nov 30 '12 at 14:18
3
@Raphael: Just look at the definition of@expandtwoargs
and define a macro for three arguments. Should not be any trouble.
– Martin Scharrer♦
Dec 1 '12 at 8:46
3
Relevant: A tutorial onexpandafter
– Werner
Oct 16 '15 at 23:34
add a comment |
26
That’s a typical example of cargo cult programming. I think I’m allowed to make this observation without being insulting since my TeX code looks exactly like this, i.e. I have the exact same problem. :-( All this to say that I was about to ask the exact same question.
– Konrad Rudolph
Jul 28 '10 at 10:54
4
Andrew, just because I saw your example above: I recently discovered the LaTeX2e macro@expandtwoargscommand{<arg1>}{<arg2>}
which expands the two arguments usingedef
before feeding it tocommand
.
– Martin Scharrer♦
Feb 15 '11 at 17:38
1
@MartinScharrer That's neat! Unfortunately, there does not seem to be an equivalent for three (or more?) parameters. :/
– Raphael
Nov 30 '12 at 14:18
3
@Raphael: Just look at the definition of@expandtwoargs
and define a macro for three arguments. Should not be any trouble.
– Martin Scharrer♦
Dec 1 '12 at 8:46
3
Relevant: A tutorial onexpandafter
– Werner
Oct 16 '15 at 23:34
26
26
That’s a typical example of cargo cult programming. I think I’m allowed to make this observation without being insulting since my TeX code looks exactly like this, i.e. I have the exact same problem. :-( All this to say that I was about to ask the exact same question.
– Konrad Rudolph
Jul 28 '10 at 10:54
That’s a typical example of cargo cult programming. I think I’m allowed to make this observation without being insulting since my TeX code looks exactly like this, i.e. I have the exact same problem. :-( All this to say that I was about to ask the exact same question.
– Konrad Rudolph
Jul 28 '10 at 10:54
4
4
Andrew, just because I saw your example above: I recently discovered the LaTeX2e macro
@expandtwoargscommand{<arg1>}{<arg2>}
which expands the two arguments using edef
before feeding it to command
.– Martin Scharrer♦
Feb 15 '11 at 17:38
Andrew, just because I saw your example above: I recently discovered the LaTeX2e macro
@expandtwoargscommand{<arg1>}{<arg2>}
which expands the two arguments using edef
before feeding it to command
.– Martin Scharrer♦
Feb 15 '11 at 17:38
1
1
@MartinScharrer That's neat! Unfortunately, there does not seem to be an equivalent for three (or more?) parameters. :/
– Raphael
Nov 30 '12 at 14:18
@MartinScharrer That's neat! Unfortunately, there does not seem to be an equivalent for three (or more?) parameters. :/
– Raphael
Nov 30 '12 at 14:18
3
3
@Raphael: Just look at the definition of
@expandtwoargs
and define a macro for three arguments. Should not be any trouble.– Martin Scharrer♦
Dec 1 '12 at 8:46
@Raphael: Just look at the definition of
@expandtwoargs
and define a macro for three arguments. Should not be any trouble.– Martin Scharrer♦
Dec 1 '12 at 8:46
3
3
Relevant: A tutorial on
expandafter
– Werner
Oct 16 '15 at 23:34
Relevant: A tutorial on
expandafter
– Werner
Oct 16 '15 at 23:34
add a comment |
5 Answers
5
active
oldest
votes
Expansion is a complicated area of TeX programming. I'll try to explain the key primitives involved first, then try to come up with some examples.
The expandafter
primitive expands the token after the next one. So
expandafterdefcsname an-awkward-nameendcsname
will expand csname
before def
. So after one expansion the above turns into
defan-awkward-name
which will then do its thing. Life becomes more complex when you want to step further ahead, and it soon becomes very hard to track what is going on.
The edef
> primitive does a full expansion of what is given as its argument (in contrast to def
, which simply stores the input). So
defexamplea{more stuff}
edefexampleb{Some stuff csname exampleaendcsname}
will expand the csname nameendcsname
to examplea
, then expand that to leave a final definition of exampleb
as 'Some stuff more stuff'.
Now, noexpand
comes in by preventing edef
from doing an expansion of the next token. So if I modify my above example to read
defexamplea{more stuff}
edefexampleb{Some stuff expandafternoexpandcsname exampleaendcsname}
then what will happen is that the edef
will execute the expandafter
, which will turn the above effectively into
defexamplea{more stuff}
edefexampleb{Some stuff noexpandexamplea}
Now the noexpand
will operate (disappearing in the process), leaving the definition of exampleb
as 'Some stuff examplea'.
We can use this ability to cut down on expandafter
use, but there are a couple of other things to know. First, e-TeX includes an additional primitive unexpanded
, which will prevent expansion of multiple tokens. Secondly, there are various special cases where you don't need quite so many expandafter
statements. A classic example is from within csname
, as this will do expansion anyway. So you'll see things like
csname nameexpandafterendcsnametoken
which will expand token
before name
.
Back to your example. In the first one, there isn't much to do: as the entire point is to have a dynamic name (#1
), doing an edef
at point-of-definition doesn't really make sense. The closest one can get is something like
edefcohtheory{%
noexpandnewcommandexpandafternoexpandcsname foofuncendcsname[1][*]{%
noexpandMakeUppercase{foo}^{##1}}%
}
What will happen here is that newcommand
and MakeUppercase
will be protected from expansion, and the csname
will only expand once. (Tokens which don't have an expansion don't need protection, which is why things like '[1]' are simply included as is.) Of course, this is something of a 'toy' as all it does is create a fixed foofunc
.
For your second example, you could instead to
begingroup
edeftemp{%
endgroup
noexpandcommand
{unexpandedexpandafter{argone}}%
{unexpandedexpandafter{argtwo}}%
}
temp
I'm using a couple of extra ideas here. First, the group is used so that temp
is not altered anywhere other than where I'm using it. The endgroup
primitive will do nothing inside the edef
, and so will still be there to close the group when temp
is used. Secondly, unexpanded
works like a toks, and so will respect the expandafter
after it but before the {
. This cuts down on an unnecessary expandafter
.
There are more wrinkles to this, and often there are several equally-efficient and clear methods. You are best off posting specific examples, and seeking advice on how they might be achieved.
The solution I went for is a cross of your two approaches:defcohtheory#1{defname{csname#1funcendcsname} edeftemp{noexpandgdefname{...}}temp}
. Thanks for your time!
– Michaël
Jan 16 '18 at 16:00
add a comment |
One difference of expandafter
and edef
is their behaviour towards protected macros.
eTeX provides the prefix protected
which can be used before def
and friends to define a protected, i.e. "robust" macro which doesn't expand inside an edef
context (like in write
). However, expandafter
does expand such a macro.
See the following example (works with eTeX and LaTeX):
protecteddefpempty{}
edefwithedef{xpempty x}
expandafterdefexpandafterwithexpandafterexpandafter{expandafter xpempty x}
tt
meaningpempty.
meaningwithedef.
meaningwithexpandafter.
Gives:
protected macro:->.
macro:->xpempty x.
macro:->xx.
There are also the situations where TeX is expanding tokens, like after &
and cr
inside a halign
. Here TeX stops when finding a protected macro without expanding it. However, if TeX is expanding tokens while in number reading mode like for ifnum
protected macros are also expanded.
4
The details of exactly when protected macros are not expanded are in the e-TeX manual.
– Joseph Wright♦
Feb 26 '11 at 20:06
add a comment |
For the particular problem of creating control sequences dynamically, I suggest you use something like
defcsarg #1{%
begingroup
expandafter
endgroup
expandafter #1csname
}
You use it like
csargmycommandbuilder <whatever> endcsname
You can even use it like this
csargmycommandbuilder <whatever> expandafterendcsname
csname <whatever2> expandafterendcsname
csname <whatever3> endcsname
However, take care with the spaces. The above code constructs control sequences that have spaces in their names!
add a comment |
Sometimes having a few helper macros makes the code much more readable. For example, in ConTeXt, typically your first macro will be written as
defcohtheory#1%
{setvalue{#1func}{dodoubleargumentdocohtheory[#1]}}
defdocohtheory[#1][#2]%
{#1^{ifsecondargument #2 else * fi}}
where setvalue
is roughly equivalent to the expandafter newcommand bit. (ignore the difference in the manner in which optional arguments are handled).
The second macro will typically be written as
{command{argone}{argtwo}}
where expanded
fully expands its arguments. expanded
is defined roughly in the same manner as Joseph's temp
macro, but uses xdef
instead of edef
.
add a comment |
To make this answers complete, one has to know, that TeX uses scopes, that are regions, where the defined macros are know. If you leave that region, the macro (and of course its content) will be destroyed. Lets make an example:
defa{foo}
{
defa{bar}
The actual content of verb|a| is a
}
The actual value of verb|a| is a
will produce
The reason is due to the fact, that the braces {}
form a new scope. Within this scope, the macro a
is local, so to say: it is a quite new macro which stores different content compared to the still existing macro with the same name but resting in a different scope. Therefore, the first call of a
results in the content "bar". Afterwards the scope area ends, the local variable is destroyed and the macro, that belongs to the surrounding scope is "restored". The second call of a
from the outer scope will present the content, that was initially stored in a
: "foo".
If you need to work on the same value in different scopes, you have to use a global variable. Here is another example, to make the point clear:
%% Second example with b
{
globaldefb{baz}
%% Do some things on b
}
The actual value of verb|b|, defined in a not more existing scope is
still `b'.
And the result:
Instead of the above more literal code, I could also have used the shorter form with gdef
:
%% Second example with b
{
gdefb{baz}
%% Do some things on b
}
The actual value of verb|b|, defined in a not more existing scope is
still `b'.
The result is still the same:
Please see the other (real good!) answers about the difference between the normal def
command, and its companion, the expanding version edef
. You can, of course, play the game with expanding macros in the local scope or in the global scope:
%% Third example with edef and globaledef
%% Define the variable foo to show, where and why this is happening.
%% First: the value before the new scope
deffoo{before}
defa{foo}
edefb{foo}
defc{}
defd{}
{
%% Second: within the scope
deffoo{within}
defc{foo}
edefd{foo}
globaldefe{foo}
globaledeff{foo}
}
%% Third: after the scope was left, now again in the global scope
deffoo{after}
Results
begin{tabular}{@{} cc @{}}
toprule
multicolumn{1}{@{} H}{Variable} & multicolumn{1}{H @{}}{Content} \
midrule
a & a \
b & b \
c & c \
d & d \
e & e \
f & f \
bottomrule
end{tabular}
It should not be surprising, that the variables c
and d
are still empty, as they have not been defined global
, when they were manipulated in the scope:
Of course, again I could have saved typing labour, by replacing globaldef
with gdef
(see above) and globaledef
with xdef
. So this is an example with all four kinds of def: def
, edef
, gdef
and xdef
.
Though it explains well about the scopes I think this is the wrong question for this answer because this is strictly about expansion not scoping.
– percusse
Feb 11 '17 at 11:21
@percusse Thanks for your kind words. I had asked the question, what are the differences between the four?def
s, as I had not found an answer in TeX.SE. My question was marked duplicate with respect to this question, and I must agree, that to some kind of extent, this is true. In the above answers,gdef
andxdef
are missing. In a more broader view, scopes also affect where something is expanded and where not, see my last example with variablesc
andd
. But if you have a strict view, you are right.
– Jan
Feb 11 '17 at 11:26
That's a wrong duplicate closing reason in my opinion
– percusse
Feb 11 '17 at 11:43
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f451%2fwhen-to-use-edef-noexpand-and-expandafter%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
Expansion is a complicated area of TeX programming. I'll try to explain the key primitives involved first, then try to come up with some examples.
The expandafter
primitive expands the token after the next one. So
expandafterdefcsname an-awkward-nameendcsname
will expand csname
before def
. So after one expansion the above turns into
defan-awkward-name
which will then do its thing. Life becomes more complex when you want to step further ahead, and it soon becomes very hard to track what is going on.
The edef
> primitive does a full expansion of what is given as its argument (in contrast to def
, which simply stores the input). So
defexamplea{more stuff}
edefexampleb{Some stuff csname exampleaendcsname}
will expand the csname nameendcsname
to examplea
, then expand that to leave a final definition of exampleb
as 'Some stuff more stuff'.
Now, noexpand
comes in by preventing edef
from doing an expansion of the next token. So if I modify my above example to read
defexamplea{more stuff}
edefexampleb{Some stuff expandafternoexpandcsname exampleaendcsname}
then what will happen is that the edef
will execute the expandafter
, which will turn the above effectively into
defexamplea{more stuff}
edefexampleb{Some stuff noexpandexamplea}
Now the noexpand
will operate (disappearing in the process), leaving the definition of exampleb
as 'Some stuff examplea'.
We can use this ability to cut down on expandafter
use, but there are a couple of other things to know. First, e-TeX includes an additional primitive unexpanded
, which will prevent expansion of multiple tokens. Secondly, there are various special cases where you don't need quite so many expandafter
statements. A classic example is from within csname
, as this will do expansion anyway. So you'll see things like
csname nameexpandafterendcsnametoken
which will expand token
before name
.
Back to your example. In the first one, there isn't much to do: as the entire point is to have a dynamic name (#1
), doing an edef
at point-of-definition doesn't really make sense. The closest one can get is something like
edefcohtheory{%
noexpandnewcommandexpandafternoexpandcsname foofuncendcsname[1][*]{%
noexpandMakeUppercase{foo}^{##1}}%
}
What will happen here is that newcommand
and MakeUppercase
will be protected from expansion, and the csname
will only expand once. (Tokens which don't have an expansion don't need protection, which is why things like '[1]' are simply included as is.) Of course, this is something of a 'toy' as all it does is create a fixed foofunc
.
For your second example, you could instead to
begingroup
edeftemp{%
endgroup
noexpandcommand
{unexpandedexpandafter{argone}}%
{unexpandedexpandafter{argtwo}}%
}
temp
I'm using a couple of extra ideas here. First, the group is used so that temp
is not altered anywhere other than where I'm using it. The endgroup
primitive will do nothing inside the edef
, and so will still be there to close the group when temp
is used. Secondly, unexpanded
works like a toks, and so will respect the expandafter
after it but before the {
. This cuts down on an unnecessary expandafter
.
There are more wrinkles to this, and often there are several equally-efficient and clear methods. You are best off posting specific examples, and seeking advice on how they might be achieved.
The solution I went for is a cross of your two approaches:defcohtheory#1{defname{csname#1funcendcsname} edeftemp{noexpandgdefname{...}}temp}
. Thanks for your time!
– Michaël
Jan 16 '18 at 16:00
add a comment |
Expansion is a complicated area of TeX programming. I'll try to explain the key primitives involved first, then try to come up with some examples.
The expandafter
primitive expands the token after the next one. So
expandafterdefcsname an-awkward-nameendcsname
will expand csname
before def
. So after one expansion the above turns into
defan-awkward-name
which will then do its thing. Life becomes more complex when you want to step further ahead, and it soon becomes very hard to track what is going on.
The edef
> primitive does a full expansion of what is given as its argument (in contrast to def
, which simply stores the input). So
defexamplea{more stuff}
edefexampleb{Some stuff csname exampleaendcsname}
will expand the csname nameendcsname
to examplea
, then expand that to leave a final definition of exampleb
as 'Some stuff more stuff'.
Now, noexpand
comes in by preventing edef
from doing an expansion of the next token. So if I modify my above example to read
defexamplea{more stuff}
edefexampleb{Some stuff expandafternoexpandcsname exampleaendcsname}
then what will happen is that the edef
will execute the expandafter
, which will turn the above effectively into
defexamplea{more stuff}
edefexampleb{Some stuff noexpandexamplea}
Now the noexpand
will operate (disappearing in the process), leaving the definition of exampleb
as 'Some stuff examplea'.
We can use this ability to cut down on expandafter
use, but there are a couple of other things to know. First, e-TeX includes an additional primitive unexpanded
, which will prevent expansion of multiple tokens. Secondly, there are various special cases where you don't need quite so many expandafter
statements. A classic example is from within csname
, as this will do expansion anyway. So you'll see things like
csname nameexpandafterendcsnametoken
which will expand token
before name
.
Back to your example. In the first one, there isn't much to do: as the entire point is to have a dynamic name (#1
), doing an edef
at point-of-definition doesn't really make sense. The closest one can get is something like
edefcohtheory{%
noexpandnewcommandexpandafternoexpandcsname foofuncendcsname[1][*]{%
noexpandMakeUppercase{foo}^{##1}}%
}
What will happen here is that newcommand
and MakeUppercase
will be protected from expansion, and the csname
will only expand once. (Tokens which don't have an expansion don't need protection, which is why things like '[1]' are simply included as is.) Of course, this is something of a 'toy' as all it does is create a fixed foofunc
.
For your second example, you could instead to
begingroup
edeftemp{%
endgroup
noexpandcommand
{unexpandedexpandafter{argone}}%
{unexpandedexpandafter{argtwo}}%
}
temp
I'm using a couple of extra ideas here. First, the group is used so that temp
is not altered anywhere other than where I'm using it. The endgroup
primitive will do nothing inside the edef
, and so will still be there to close the group when temp
is used. Secondly, unexpanded
works like a toks, and so will respect the expandafter
after it but before the {
. This cuts down on an unnecessary expandafter
.
There are more wrinkles to this, and often there are several equally-efficient and clear methods. You are best off posting specific examples, and seeking advice on how they might be achieved.
The solution I went for is a cross of your two approaches:defcohtheory#1{defname{csname#1funcendcsname} edeftemp{noexpandgdefname{...}}temp}
. Thanks for your time!
– Michaël
Jan 16 '18 at 16:00
add a comment |
Expansion is a complicated area of TeX programming. I'll try to explain the key primitives involved first, then try to come up with some examples.
The expandafter
primitive expands the token after the next one. So
expandafterdefcsname an-awkward-nameendcsname
will expand csname
before def
. So after one expansion the above turns into
defan-awkward-name
which will then do its thing. Life becomes more complex when you want to step further ahead, and it soon becomes very hard to track what is going on.
The edef
> primitive does a full expansion of what is given as its argument (in contrast to def
, which simply stores the input). So
defexamplea{more stuff}
edefexampleb{Some stuff csname exampleaendcsname}
will expand the csname nameendcsname
to examplea
, then expand that to leave a final definition of exampleb
as 'Some stuff more stuff'.
Now, noexpand
comes in by preventing edef
from doing an expansion of the next token. So if I modify my above example to read
defexamplea{more stuff}
edefexampleb{Some stuff expandafternoexpandcsname exampleaendcsname}
then what will happen is that the edef
will execute the expandafter
, which will turn the above effectively into
defexamplea{more stuff}
edefexampleb{Some stuff noexpandexamplea}
Now the noexpand
will operate (disappearing in the process), leaving the definition of exampleb
as 'Some stuff examplea'.
We can use this ability to cut down on expandafter
use, but there are a couple of other things to know. First, e-TeX includes an additional primitive unexpanded
, which will prevent expansion of multiple tokens. Secondly, there are various special cases where you don't need quite so many expandafter
statements. A classic example is from within csname
, as this will do expansion anyway. So you'll see things like
csname nameexpandafterendcsnametoken
which will expand token
before name
.
Back to your example. In the first one, there isn't much to do: as the entire point is to have a dynamic name (#1
), doing an edef
at point-of-definition doesn't really make sense. The closest one can get is something like
edefcohtheory{%
noexpandnewcommandexpandafternoexpandcsname foofuncendcsname[1][*]{%
noexpandMakeUppercase{foo}^{##1}}%
}
What will happen here is that newcommand
and MakeUppercase
will be protected from expansion, and the csname
will only expand once. (Tokens which don't have an expansion don't need protection, which is why things like '[1]' are simply included as is.) Of course, this is something of a 'toy' as all it does is create a fixed foofunc
.
For your second example, you could instead to
begingroup
edeftemp{%
endgroup
noexpandcommand
{unexpandedexpandafter{argone}}%
{unexpandedexpandafter{argtwo}}%
}
temp
I'm using a couple of extra ideas here. First, the group is used so that temp
is not altered anywhere other than where I'm using it. The endgroup
primitive will do nothing inside the edef
, and so will still be there to close the group when temp
is used. Secondly, unexpanded
works like a toks, and so will respect the expandafter
after it but before the {
. This cuts down on an unnecessary expandafter
.
There are more wrinkles to this, and often there are several equally-efficient and clear methods. You are best off posting specific examples, and seeking advice on how they might be achieved.
Expansion is a complicated area of TeX programming. I'll try to explain the key primitives involved first, then try to come up with some examples.
The expandafter
primitive expands the token after the next one. So
expandafterdefcsname an-awkward-nameendcsname
will expand csname
before def
. So after one expansion the above turns into
defan-awkward-name
which will then do its thing. Life becomes more complex when you want to step further ahead, and it soon becomes very hard to track what is going on.
The edef
> primitive does a full expansion of what is given as its argument (in contrast to def
, which simply stores the input). So
defexamplea{more stuff}
edefexampleb{Some stuff csname exampleaendcsname}
will expand the csname nameendcsname
to examplea
, then expand that to leave a final definition of exampleb
as 'Some stuff more stuff'.
Now, noexpand
comes in by preventing edef
from doing an expansion of the next token. So if I modify my above example to read
defexamplea{more stuff}
edefexampleb{Some stuff expandafternoexpandcsname exampleaendcsname}
then what will happen is that the edef
will execute the expandafter
, which will turn the above effectively into
defexamplea{more stuff}
edefexampleb{Some stuff noexpandexamplea}
Now the noexpand
will operate (disappearing in the process), leaving the definition of exampleb
as 'Some stuff examplea'.
We can use this ability to cut down on expandafter
use, but there are a couple of other things to know. First, e-TeX includes an additional primitive unexpanded
, which will prevent expansion of multiple tokens. Secondly, there are various special cases where you don't need quite so many expandafter
statements. A classic example is from within csname
, as this will do expansion anyway. So you'll see things like
csname nameexpandafterendcsnametoken
which will expand token
before name
.
Back to your example. In the first one, there isn't much to do: as the entire point is to have a dynamic name (#1
), doing an edef
at point-of-definition doesn't really make sense. The closest one can get is something like
edefcohtheory{%
noexpandnewcommandexpandafternoexpandcsname foofuncendcsname[1][*]{%
noexpandMakeUppercase{foo}^{##1}}%
}
What will happen here is that newcommand
and MakeUppercase
will be protected from expansion, and the csname
will only expand once. (Tokens which don't have an expansion don't need protection, which is why things like '[1]' are simply included as is.) Of course, this is something of a 'toy' as all it does is create a fixed foofunc
.
For your second example, you could instead to
begingroup
edeftemp{%
endgroup
noexpandcommand
{unexpandedexpandafter{argone}}%
{unexpandedexpandafter{argtwo}}%
}
temp
I'm using a couple of extra ideas here. First, the group is used so that temp
is not altered anywhere other than where I'm using it. The endgroup
primitive will do nothing inside the edef
, and so will still be there to close the group when temp
is used. Secondly, unexpanded
works like a toks, and so will respect the expandafter
after it but before the {
. This cuts down on an unnecessary expandafter
.
There are more wrinkles to this, and often there are several equally-efficient and clear methods. You are best off posting specific examples, and seeking advice on how they might be achieved.
edited Jan 16 '18 at 14:14
answered Jul 28 '10 at 20:22
Joseph Wright♦Joseph Wright
206k23566895
206k23566895
The solution I went for is a cross of your two approaches:defcohtheory#1{defname{csname#1funcendcsname} edeftemp{noexpandgdefname{...}}temp}
. Thanks for your time!
– Michaël
Jan 16 '18 at 16:00
add a comment |
The solution I went for is a cross of your two approaches:defcohtheory#1{defname{csname#1funcendcsname} edeftemp{noexpandgdefname{...}}temp}
. Thanks for your time!
– Michaël
Jan 16 '18 at 16:00
The solution I went for is a cross of your two approaches:
defcohtheory#1{defname{csname#1funcendcsname} edeftemp{noexpandgdefname{...}}temp}
. Thanks for your time!– Michaël
Jan 16 '18 at 16:00
The solution I went for is a cross of your two approaches:
defcohtheory#1{defname{csname#1funcendcsname} edeftemp{noexpandgdefname{...}}temp}
. Thanks for your time!– Michaël
Jan 16 '18 at 16:00
add a comment |
One difference of expandafter
and edef
is their behaviour towards protected macros.
eTeX provides the prefix protected
which can be used before def
and friends to define a protected, i.e. "robust" macro which doesn't expand inside an edef
context (like in write
). However, expandafter
does expand such a macro.
See the following example (works with eTeX and LaTeX):
protecteddefpempty{}
edefwithedef{xpempty x}
expandafterdefexpandafterwithexpandafterexpandafter{expandafter xpempty x}
tt
meaningpempty.
meaningwithedef.
meaningwithexpandafter.
Gives:
protected macro:->.
macro:->xpempty x.
macro:->xx.
There are also the situations where TeX is expanding tokens, like after &
and cr
inside a halign
. Here TeX stops when finding a protected macro without expanding it. However, if TeX is expanding tokens while in number reading mode like for ifnum
protected macros are also expanded.
4
The details of exactly when protected macros are not expanded are in the e-TeX manual.
– Joseph Wright♦
Feb 26 '11 at 20:06
add a comment |
One difference of expandafter
and edef
is their behaviour towards protected macros.
eTeX provides the prefix protected
which can be used before def
and friends to define a protected, i.e. "robust" macro which doesn't expand inside an edef
context (like in write
). However, expandafter
does expand such a macro.
See the following example (works with eTeX and LaTeX):
protecteddefpempty{}
edefwithedef{xpempty x}
expandafterdefexpandafterwithexpandafterexpandafter{expandafter xpempty x}
tt
meaningpempty.
meaningwithedef.
meaningwithexpandafter.
Gives:
protected macro:->.
macro:->xpempty x.
macro:->xx.
There are also the situations where TeX is expanding tokens, like after &
and cr
inside a halign
. Here TeX stops when finding a protected macro without expanding it. However, if TeX is expanding tokens while in number reading mode like for ifnum
protected macros are also expanded.
4
The details of exactly when protected macros are not expanded are in the e-TeX manual.
– Joseph Wright♦
Feb 26 '11 at 20:06
add a comment |
One difference of expandafter
and edef
is their behaviour towards protected macros.
eTeX provides the prefix protected
which can be used before def
and friends to define a protected, i.e. "robust" macro which doesn't expand inside an edef
context (like in write
). However, expandafter
does expand such a macro.
See the following example (works with eTeX and LaTeX):
protecteddefpempty{}
edefwithedef{xpempty x}
expandafterdefexpandafterwithexpandafterexpandafter{expandafter xpempty x}
tt
meaningpempty.
meaningwithedef.
meaningwithexpandafter.
Gives:
protected macro:->.
macro:->xpempty x.
macro:->xx.
There are also the situations where TeX is expanding tokens, like after &
and cr
inside a halign
. Here TeX stops when finding a protected macro without expanding it. However, if TeX is expanding tokens while in number reading mode like for ifnum
protected macros are also expanded.
One difference of expandafter
and edef
is their behaviour towards protected macros.
eTeX provides the prefix protected
which can be used before def
and friends to define a protected, i.e. "robust" macro which doesn't expand inside an edef
context (like in write
). However, expandafter
does expand such a macro.
See the following example (works with eTeX and LaTeX):
protecteddefpempty{}
edefwithedef{xpempty x}
expandafterdefexpandafterwithexpandafterexpandafter{expandafter xpempty x}
tt
meaningpempty.
meaningwithedef.
meaningwithexpandafter.
Gives:
protected macro:->.
macro:->xpempty x.
macro:->xx.
There are also the situations where TeX is expanding tokens, like after &
and cr
inside a halign
. Here TeX stops when finding a protected macro without expanding it. However, if TeX is expanding tokens while in number reading mode like for ifnum
protected macros are also expanded.
edited Jan 16 '18 at 8:11
answered Feb 26 '11 at 20:05
Martin Scharrer♦Martin Scharrer
204k47653831
204k47653831
4
The details of exactly when protected macros are not expanded are in the e-TeX manual.
– Joseph Wright♦
Feb 26 '11 at 20:06
add a comment |
4
The details of exactly when protected macros are not expanded are in the e-TeX manual.
– Joseph Wright♦
Feb 26 '11 at 20:06
4
4
The details of exactly when protected macros are not expanded are in the e-TeX manual.
– Joseph Wright♦
Feb 26 '11 at 20:06
The details of exactly when protected macros are not expanded are in the e-TeX manual.
– Joseph Wright♦
Feb 26 '11 at 20:06
add a comment |
For the particular problem of creating control sequences dynamically, I suggest you use something like
defcsarg #1{%
begingroup
expandafter
endgroup
expandafter #1csname
}
You use it like
csargmycommandbuilder <whatever> endcsname
You can even use it like this
csargmycommandbuilder <whatever> expandafterendcsname
csname <whatever2> expandafterendcsname
csname <whatever3> endcsname
However, take care with the spaces. The above code constructs control sequences that have spaces in their names!
add a comment |
For the particular problem of creating control sequences dynamically, I suggest you use something like
defcsarg #1{%
begingroup
expandafter
endgroup
expandafter #1csname
}
You use it like
csargmycommandbuilder <whatever> endcsname
You can even use it like this
csargmycommandbuilder <whatever> expandafterendcsname
csname <whatever2> expandafterendcsname
csname <whatever3> endcsname
However, take care with the spaces. The above code constructs control sequences that have spaces in their names!
add a comment |
For the particular problem of creating control sequences dynamically, I suggest you use something like
defcsarg #1{%
begingroup
expandafter
endgroup
expandafter #1csname
}
You use it like
csargmycommandbuilder <whatever> endcsname
You can even use it like this
csargmycommandbuilder <whatever> expandafterendcsname
csname <whatever2> expandafterendcsname
csname <whatever3> endcsname
However, take care with the spaces. The above code constructs control sequences that have spaces in their names!
For the particular problem of creating control sequences dynamically, I suggest you use something like
defcsarg #1{%
begingroup
expandafter
endgroup
expandafter #1csname
}
You use it like
csargmycommandbuilder <whatever> endcsname
You can even use it like this
csargmycommandbuilder <whatever> expandafterendcsname
csname <whatever2> expandafterendcsname
csname <whatever3> endcsname
However, take care with the spaces. The above code constructs control sequences that have spaces in their names!
answered Aug 4 '10 at 21:45
Jonathan FineJonathan Fine
1,6831213
1,6831213
add a comment |
add a comment |
Sometimes having a few helper macros makes the code much more readable. For example, in ConTeXt, typically your first macro will be written as
defcohtheory#1%
{setvalue{#1func}{dodoubleargumentdocohtheory[#1]}}
defdocohtheory[#1][#2]%
{#1^{ifsecondargument #2 else * fi}}
where setvalue
is roughly equivalent to the expandafter newcommand bit. (ignore the difference in the manner in which optional arguments are handled).
The second macro will typically be written as
{command{argone}{argtwo}}
where expanded
fully expands its arguments. expanded
is defined roughly in the same manner as Joseph's temp
macro, but uses xdef
instead of edef
.
add a comment |
Sometimes having a few helper macros makes the code much more readable. For example, in ConTeXt, typically your first macro will be written as
defcohtheory#1%
{setvalue{#1func}{dodoubleargumentdocohtheory[#1]}}
defdocohtheory[#1][#2]%
{#1^{ifsecondargument #2 else * fi}}
where setvalue
is roughly equivalent to the expandafter newcommand bit. (ignore the difference in the manner in which optional arguments are handled).
The second macro will typically be written as
{command{argone}{argtwo}}
where expanded
fully expands its arguments. expanded
is defined roughly in the same manner as Joseph's temp
macro, but uses xdef
instead of edef
.
add a comment |
Sometimes having a few helper macros makes the code much more readable. For example, in ConTeXt, typically your first macro will be written as
defcohtheory#1%
{setvalue{#1func}{dodoubleargumentdocohtheory[#1]}}
defdocohtheory[#1][#2]%
{#1^{ifsecondargument #2 else * fi}}
where setvalue
is roughly equivalent to the expandafter newcommand bit. (ignore the difference in the manner in which optional arguments are handled).
The second macro will typically be written as
{command{argone}{argtwo}}
where expanded
fully expands its arguments. expanded
is defined roughly in the same manner as Joseph's temp
macro, but uses xdef
instead of edef
.
Sometimes having a few helper macros makes the code much more readable. For example, in ConTeXt, typically your first macro will be written as
defcohtheory#1%
{setvalue{#1func}{dodoubleargumentdocohtheory[#1]}}
defdocohtheory[#1][#2]%
{#1^{ifsecondargument #2 else * fi}}
where setvalue
is roughly equivalent to the expandafter newcommand bit. (ignore the difference in the manner in which optional arguments are handled).
The second macro will typically be written as
{command{argone}{argtwo}}
where expanded
fully expands its arguments. expanded
is defined roughly in the same manner as Joseph's temp
macro, but uses xdef
instead of edef
.
edited 6 mins ago
JouleV
14.8k22666
14.8k22666
answered Nov 14 '10 at 21:59
AdityaAditya
56k2110237
56k2110237
add a comment |
add a comment |
To make this answers complete, one has to know, that TeX uses scopes, that are regions, where the defined macros are know. If you leave that region, the macro (and of course its content) will be destroyed. Lets make an example:
defa{foo}
{
defa{bar}
The actual content of verb|a| is a
}
The actual value of verb|a| is a
will produce
The reason is due to the fact, that the braces {}
form a new scope. Within this scope, the macro a
is local, so to say: it is a quite new macro which stores different content compared to the still existing macro with the same name but resting in a different scope. Therefore, the first call of a
results in the content "bar". Afterwards the scope area ends, the local variable is destroyed and the macro, that belongs to the surrounding scope is "restored". The second call of a
from the outer scope will present the content, that was initially stored in a
: "foo".
If you need to work on the same value in different scopes, you have to use a global variable. Here is another example, to make the point clear:
%% Second example with b
{
globaldefb{baz}
%% Do some things on b
}
The actual value of verb|b|, defined in a not more existing scope is
still `b'.
And the result:
Instead of the above more literal code, I could also have used the shorter form with gdef
:
%% Second example with b
{
gdefb{baz}
%% Do some things on b
}
The actual value of verb|b|, defined in a not more existing scope is
still `b'.
The result is still the same:
Please see the other (real good!) answers about the difference between the normal def
command, and its companion, the expanding version edef
. You can, of course, play the game with expanding macros in the local scope or in the global scope:
%% Third example with edef and globaledef
%% Define the variable foo to show, where and why this is happening.
%% First: the value before the new scope
deffoo{before}
defa{foo}
edefb{foo}
defc{}
defd{}
{
%% Second: within the scope
deffoo{within}
defc{foo}
edefd{foo}
globaldefe{foo}
globaledeff{foo}
}
%% Third: after the scope was left, now again in the global scope
deffoo{after}
Results
begin{tabular}{@{} cc @{}}
toprule
multicolumn{1}{@{} H}{Variable} & multicolumn{1}{H @{}}{Content} \
midrule
a & a \
b & b \
c & c \
d & d \
e & e \
f & f \
bottomrule
end{tabular}
It should not be surprising, that the variables c
and d
are still empty, as they have not been defined global
, when they were manipulated in the scope:
Of course, again I could have saved typing labour, by replacing globaldef
with gdef
(see above) and globaledef
with xdef
. So this is an example with all four kinds of def: def
, edef
, gdef
and xdef
.
Though it explains well about the scopes I think this is the wrong question for this answer because this is strictly about expansion not scoping.
– percusse
Feb 11 '17 at 11:21
@percusse Thanks for your kind words. I had asked the question, what are the differences between the four?def
s, as I had not found an answer in TeX.SE. My question was marked duplicate with respect to this question, and I must agree, that to some kind of extent, this is true. In the above answers,gdef
andxdef
are missing. In a more broader view, scopes also affect where something is expanded and where not, see my last example with variablesc
andd
. But if you have a strict view, you are right.
– Jan
Feb 11 '17 at 11:26
That's a wrong duplicate closing reason in my opinion
– percusse
Feb 11 '17 at 11:43
add a comment |
To make this answers complete, one has to know, that TeX uses scopes, that are regions, where the defined macros are know. If you leave that region, the macro (and of course its content) will be destroyed. Lets make an example:
defa{foo}
{
defa{bar}
The actual content of verb|a| is a
}
The actual value of verb|a| is a
will produce
The reason is due to the fact, that the braces {}
form a new scope. Within this scope, the macro a
is local, so to say: it is a quite new macro which stores different content compared to the still existing macro with the same name but resting in a different scope. Therefore, the first call of a
results in the content "bar". Afterwards the scope area ends, the local variable is destroyed and the macro, that belongs to the surrounding scope is "restored". The second call of a
from the outer scope will present the content, that was initially stored in a
: "foo".
If you need to work on the same value in different scopes, you have to use a global variable. Here is another example, to make the point clear:
%% Second example with b
{
globaldefb{baz}
%% Do some things on b
}
The actual value of verb|b|, defined in a not more existing scope is
still `b'.
And the result:
Instead of the above more literal code, I could also have used the shorter form with gdef
:
%% Second example with b
{
gdefb{baz}
%% Do some things on b
}
The actual value of verb|b|, defined in a not more existing scope is
still `b'.
The result is still the same:
Please see the other (real good!) answers about the difference between the normal def
command, and its companion, the expanding version edef
. You can, of course, play the game with expanding macros in the local scope or in the global scope:
%% Third example with edef and globaledef
%% Define the variable foo to show, where and why this is happening.
%% First: the value before the new scope
deffoo{before}
defa{foo}
edefb{foo}
defc{}
defd{}
{
%% Second: within the scope
deffoo{within}
defc{foo}
edefd{foo}
globaldefe{foo}
globaledeff{foo}
}
%% Third: after the scope was left, now again in the global scope
deffoo{after}
Results
begin{tabular}{@{} cc @{}}
toprule
multicolumn{1}{@{} H}{Variable} & multicolumn{1}{H @{}}{Content} \
midrule
a & a \
b & b \
c & c \
d & d \
e & e \
f & f \
bottomrule
end{tabular}
It should not be surprising, that the variables c
and d
are still empty, as they have not been defined global
, when they were manipulated in the scope:
Of course, again I could have saved typing labour, by replacing globaldef
with gdef
(see above) and globaledef
with xdef
. So this is an example with all four kinds of def: def
, edef
, gdef
and xdef
.
Though it explains well about the scopes I think this is the wrong question for this answer because this is strictly about expansion not scoping.
– percusse
Feb 11 '17 at 11:21
@percusse Thanks for your kind words. I had asked the question, what are the differences between the four?def
s, as I had not found an answer in TeX.SE. My question was marked duplicate with respect to this question, and I must agree, that to some kind of extent, this is true. In the above answers,gdef
andxdef
are missing. In a more broader view, scopes also affect where something is expanded and where not, see my last example with variablesc
andd
. But if you have a strict view, you are right.
– Jan
Feb 11 '17 at 11:26
That's a wrong duplicate closing reason in my opinion
– percusse
Feb 11 '17 at 11:43
add a comment |
To make this answers complete, one has to know, that TeX uses scopes, that are regions, where the defined macros are know. If you leave that region, the macro (and of course its content) will be destroyed. Lets make an example:
defa{foo}
{
defa{bar}
The actual content of verb|a| is a
}
The actual value of verb|a| is a
will produce
The reason is due to the fact, that the braces {}
form a new scope. Within this scope, the macro a
is local, so to say: it is a quite new macro which stores different content compared to the still existing macro with the same name but resting in a different scope. Therefore, the first call of a
results in the content "bar". Afterwards the scope area ends, the local variable is destroyed and the macro, that belongs to the surrounding scope is "restored". The second call of a
from the outer scope will present the content, that was initially stored in a
: "foo".
If you need to work on the same value in different scopes, you have to use a global variable. Here is another example, to make the point clear:
%% Second example with b
{
globaldefb{baz}
%% Do some things on b
}
The actual value of verb|b|, defined in a not more existing scope is
still `b'.
And the result:
Instead of the above more literal code, I could also have used the shorter form with gdef
:
%% Second example with b
{
gdefb{baz}
%% Do some things on b
}
The actual value of verb|b|, defined in a not more existing scope is
still `b'.
The result is still the same:
Please see the other (real good!) answers about the difference between the normal def
command, and its companion, the expanding version edef
. You can, of course, play the game with expanding macros in the local scope or in the global scope:
%% Third example with edef and globaledef
%% Define the variable foo to show, where and why this is happening.
%% First: the value before the new scope
deffoo{before}
defa{foo}
edefb{foo}
defc{}
defd{}
{
%% Second: within the scope
deffoo{within}
defc{foo}
edefd{foo}
globaldefe{foo}
globaledeff{foo}
}
%% Third: after the scope was left, now again in the global scope
deffoo{after}
Results
begin{tabular}{@{} cc @{}}
toprule
multicolumn{1}{@{} H}{Variable} & multicolumn{1}{H @{}}{Content} \
midrule
a & a \
b & b \
c & c \
d & d \
e & e \
f & f \
bottomrule
end{tabular}
It should not be surprising, that the variables c
and d
are still empty, as they have not been defined global
, when they were manipulated in the scope:
Of course, again I could have saved typing labour, by replacing globaldef
with gdef
(see above) and globaledef
with xdef
. So this is an example with all four kinds of def: def
, edef
, gdef
and xdef
.
To make this answers complete, one has to know, that TeX uses scopes, that are regions, where the defined macros are know. If you leave that region, the macro (and of course its content) will be destroyed. Lets make an example:
defa{foo}
{
defa{bar}
The actual content of verb|a| is a
}
The actual value of verb|a| is a
will produce
The reason is due to the fact, that the braces {}
form a new scope. Within this scope, the macro a
is local, so to say: it is a quite new macro which stores different content compared to the still existing macro with the same name but resting in a different scope. Therefore, the first call of a
results in the content "bar". Afterwards the scope area ends, the local variable is destroyed and the macro, that belongs to the surrounding scope is "restored". The second call of a
from the outer scope will present the content, that was initially stored in a
: "foo".
If you need to work on the same value in different scopes, you have to use a global variable. Here is another example, to make the point clear:
%% Second example with b
{
globaldefb{baz}
%% Do some things on b
}
The actual value of verb|b|, defined in a not more existing scope is
still `b'.
And the result:
Instead of the above more literal code, I could also have used the shorter form with gdef
:
%% Second example with b
{
gdefb{baz}
%% Do some things on b
}
The actual value of verb|b|, defined in a not more existing scope is
still `b'.
The result is still the same:
Please see the other (real good!) answers about the difference between the normal def
command, and its companion, the expanding version edef
. You can, of course, play the game with expanding macros in the local scope or in the global scope:
%% Third example with edef and globaledef
%% Define the variable foo to show, where and why this is happening.
%% First: the value before the new scope
deffoo{before}
defa{foo}
edefb{foo}
defc{}
defd{}
{
%% Second: within the scope
deffoo{within}
defc{foo}
edefd{foo}
globaldefe{foo}
globaledeff{foo}
}
%% Third: after the scope was left, now again in the global scope
deffoo{after}
Results
begin{tabular}{@{} cc @{}}
toprule
multicolumn{1}{@{} H}{Variable} & multicolumn{1}{H @{}}{Content} \
midrule
a & a \
b & b \
c & c \
d & d \
e & e \
f & f \
bottomrule
end{tabular}
It should not be surprising, that the variables c
and d
are still empty, as they have not been defined global
, when they were manipulated in the scope:
Of course, again I could have saved typing labour, by replacing globaldef
with gdef
(see above) and globaledef
with xdef
. So this is an example with all four kinds of def: def
, edef
, gdef
and xdef
.
answered Feb 11 '17 at 11:18
JanJan
3,7381630
3,7381630
Though it explains well about the scopes I think this is the wrong question for this answer because this is strictly about expansion not scoping.
– percusse
Feb 11 '17 at 11:21
@percusse Thanks for your kind words. I had asked the question, what are the differences between the four?def
s, as I had not found an answer in TeX.SE. My question was marked duplicate with respect to this question, and I must agree, that to some kind of extent, this is true. In the above answers,gdef
andxdef
are missing. In a more broader view, scopes also affect where something is expanded and where not, see my last example with variablesc
andd
. But if you have a strict view, you are right.
– Jan
Feb 11 '17 at 11:26
That's a wrong duplicate closing reason in my opinion
– percusse
Feb 11 '17 at 11:43
add a comment |
Though it explains well about the scopes I think this is the wrong question for this answer because this is strictly about expansion not scoping.
– percusse
Feb 11 '17 at 11:21
@percusse Thanks for your kind words. I had asked the question, what are the differences between the four?def
s, as I had not found an answer in TeX.SE. My question was marked duplicate with respect to this question, and I must agree, that to some kind of extent, this is true. In the above answers,gdef
andxdef
are missing. In a more broader view, scopes also affect where something is expanded and where not, see my last example with variablesc
andd
. But if you have a strict view, you are right.
– Jan
Feb 11 '17 at 11:26
That's a wrong duplicate closing reason in my opinion
– percusse
Feb 11 '17 at 11:43
Though it explains well about the scopes I think this is the wrong question for this answer because this is strictly about expansion not scoping.
– percusse
Feb 11 '17 at 11:21
Though it explains well about the scopes I think this is the wrong question for this answer because this is strictly about expansion not scoping.
– percusse
Feb 11 '17 at 11:21
@percusse Thanks for your kind words. I had asked the question, what are the differences between the four
?def
s, as I had not found an answer in TeX.SE. My question was marked duplicate with respect to this question, and I must agree, that to some kind of extent, this is true. In the above answers, gdef
and xdef
are missing. In a more broader view, scopes also affect where something is expanded and where not, see my last example with variables c
and d
. But if you have a strict view, you are right.– Jan
Feb 11 '17 at 11:26
@percusse Thanks for your kind words. I had asked the question, what are the differences between the four
?def
s, as I had not found an answer in TeX.SE. My question was marked duplicate with respect to this question, and I must agree, that to some kind of extent, this is true. In the above answers, gdef
and xdef
are missing. In a more broader view, scopes also affect where something is expanded and where not, see my last example with variables c
and d
. But if you have a strict view, you are right.– Jan
Feb 11 '17 at 11:26
That's a wrong duplicate closing reason in my opinion
– percusse
Feb 11 '17 at 11:43
That's a wrong duplicate closing reason in my opinion
– percusse
Feb 11 '17 at 11:43
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f451%2fwhen-to-use-edef-noexpand-and-expandafter%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
26
That’s a typical example of cargo cult programming. I think I’m allowed to make this observation without being insulting since my TeX code looks exactly like this, i.e. I have the exact same problem. :-( All this to say that I was about to ask the exact same question.
– Konrad Rudolph
Jul 28 '10 at 10:54
4
Andrew, just because I saw your example above: I recently discovered the LaTeX2e macro
@expandtwoargscommand{<arg1>}{<arg2>}
which expands the two arguments usingedef
before feeding it tocommand
.– Martin Scharrer♦
Feb 15 '11 at 17:38
1
@MartinScharrer That's neat! Unfortunately, there does not seem to be an equivalent for three (or more?) parameters. :/
– Raphael
Nov 30 '12 at 14:18
3
@Raphael: Just look at the definition of
@expandtwoargs
and define a macro for three arguments. Should not be any trouble.– Martin Scharrer♦
Dec 1 '12 at 8:46
3
Relevant: A tutorial on
expandafter
– Werner
Oct 16 '15 at 23:34