f-type expansionDoes expanded replace the romannumeral trick for expansion?Expl V-type argument no fully expanding as I expectedLaTeX3 Property lists and expansionLaTeX3 Expansion without exp_after:wNexpl3 property lists and expansionProblem with expansion in expl3Math functions and expansion issuesProtected expansion in expl3Macro expansion in TikZ nodeexpl3 function for fixed number of expansion stepsDo quarks have to be defined as macros expanding to themselves?

How to get cool night-vision without lame drawbacks?

Parameterize chained calls to a utility program in Bash

How does the spell Remove Curse interact with a Sword of Vengeance?

Why do textbooks often include the solutions to odd or even numbered problems but not both?

If I wouldn't want to read the story, is writing it still a good idea?

Count All Possible Unique Combinations of Letters in a Word

Helping ease my back pain when I'm studying 13 hours everyday, even weekends

What was the Shuttle Carrier Aircraft escape tunnel?

Do I have to explain the mechanical superiority of the player-character within the fiction of the game?

How long would it take to cross the Channel in 1890's?

How many people are necessary to maintain modern civilisation?

What's the difference between a deep fryer and a chip pan?

Should I prioritize my 401k over my student loans?

Trainee keeps missing deadlines for independent learning

Can someone suggest a path to study Mordell-Weil theorem for someone studying on their own?

Understanding the reasoning of the woman who agreed with King Solomon to "cut the baby in half"

Is it illegal to withhold someone's passport and green card in California?

Is a single radon-daughter atom in air a solid?

How large would a mega structure have to be to host 1 billion people indefinitely?

Loss of power when I remove item from the outlet

What can I do with a research project that is my university’s intellectual property?

Why use cross notes in sheet music for hip hop tracks?

What exactly is the 'online' in OLAP and OLTP?

How does a blind passenger not die, if driver becomes unconscious



f-type expansion


Does expanded replace the romannumeral trick for expansion?Expl V-type argument no fully expanding as I expectedLaTeX3 Property lists and expansionLaTeX3 Expansion without exp_after:wNexpl3 property lists and expansionProblem with expansion in expl3Math functions and expansion issuesProtected expansion in expl3Macro expansion in TikZ nodeexpl3 function for fixed number of expansion stepsDo quarks have to be defined as macros expanding to themselves?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








11















I am still struggling with understanding the f-type expansion. What is it all about? The explanation on page 2 in interface3.pdf is not really satisfying.



In the given example



tl_set:Nn l_mya_tl A 
tl_set:Nn l_myb_tl B
tl_set:Nf l_mya_tl l_mya_tl l_myb_tl


, how can a check that the content of l_mya_tl is actually Al_myb_tl?



Does it matter that l_mya_tl is re-used in order to be set on the third line, and not another, hitherto unused token list variable, say l_myc_tl?



Why does expansion stop after expanding l_mya_tl as it is expandable after all?



Is there any thinkable scenario where f-expansion would continue after expanding the first token (l_mya_tl, here)? How would l_mya_tl need to be crafted in order to not interrupt further expansion?



Why would someone want to use f-expansion, which stops at some unpredictable place, when the argument is expected to be really fully expanded? (This is what f as in "fully" means to me.)










share|improve this question
























  • f-type expansion ends with the first-encountered unexpandable token. If this token is a space, it is gobbled. You want e-type expansion, I guess.

    – egreg
    Jun 5 at 9:12











  • Thank you, it is more a general question about the purpose of this expansion type. Under which circumstances would I want to use f instead of x or e expansion?

    – AlexG
    Jun 5 at 9:15






  • 1





    it is a thin wrapper around romannumeral with e now available it is possibly less useful than it was, but advantage over x that it can be used in expansion contexts

    – David Carlisle
    Jun 5 at 10:13


















11















I am still struggling with understanding the f-type expansion. What is it all about? The explanation on page 2 in interface3.pdf is not really satisfying.



In the given example



tl_set:Nn l_mya_tl A 
tl_set:Nn l_myb_tl B
tl_set:Nf l_mya_tl l_mya_tl l_myb_tl


, how can a check that the content of l_mya_tl is actually Al_myb_tl?



Does it matter that l_mya_tl is re-used in order to be set on the third line, and not another, hitherto unused token list variable, say l_myc_tl?



Why does expansion stop after expanding l_mya_tl as it is expandable after all?



Is there any thinkable scenario where f-expansion would continue after expanding the first token (l_mya_tl, here)? How would l_mya_tl need to be crafted in order to not interrupt further expansion?



Why would someone want to use f-expansion, which stops at some unpredictable place, when the argument is expected to be really fully expanded? (This is what f as in "fully" means to me.)










share|improve this question
























  • f-type expansion ends with the first-encountered unexpandable token. If this token is a space, it is gobbled. You want e-type expansion, I guess.

    – egreg
    Jun 5 at 9:12











  • Thank you, it is more a general question about the purpose of this expansion type. Under which circumstances would I want to use f instead of x or e expansion?

    – AlexG
    Jun 5 at 9:15






  • 1





    it is a thin wrapper around romannumeral with e now available it is possibly less useful than it was, but advantage over x that it can be used in expansion contexts

    – David Carlisle
    Jun 5 at 10:13














11












11








11








I am still struggling with understanding the f-type expansion. What is it all about? The explanation on page 2 in interface3.pdf is not really satisfying.



In the given example



tl_set:Nn l_mya_tl A 
tl_set:Nn l_myb_tl B
tl_set:Nf l_mya_tl l_mya_tl l_myb_tl


, how can a check that the content of l_mya_tl is actually Al_myb_tl?



Does it matter that l_mya_tl is re-used in order to be set on the third line, and not another, hitherto unused token list variable, say l_myc_tl?



Why does expansion stop after expanding l_mya_tl as it is expandable after all?



Is there any thinkable scenario where f-expansion would continue after expanding the first token (l_mya_tl, here)? How would l_mya_tl need to be crafted in order to not interrupt further expansion?



Why would someone want to use f-expansion, which stops at some unpredictable place, when the argument is expected to be really fully expanded? (This is what f as in "fully" means to me.)










share|improve this question
















I am still struggling with understanding the f-type expansion. What is it all about? The explanation on page 2 in interface3.pdf is not really satisfying.



In the given example



tl_set:Nn l_mya_tl A 
tl_set:Nn l_myb_tl B
tl_set:Nf l_mya_tl l_mya_tl l_myb_tl


, how can a check that the content of l_mya_tl is actually Al_myb_tl?



Does it matter that l_mya_tl is re-used in order to be set on the third line, and not another, hitherto unused token list variable, say l_myc_tl?



Why does expansion stop after expanding l_mya_tl as it is expandable after all?



Is there any thinkable scenario where f-expansion would continue after expanding the first token (l_mya_tl, here)? How would l_mya_tl need to be crafted in order to not interrupt further expansion?



Why would someone want to use f-expansion, which stops at some unpredictable place, when the argument is expected to be really fully expanded? (This is what f as in "fully" means to me.)







expl3






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jun 5 at 9:29







AlexG

















asked Jun 5 at 9:09









AlexGAlexG

35.4k484152




35.4k484152












  • f-type expansion ends with the first-encountered unexpandable token. If this token is a space, it is gobbled. You want e-type expansion, I guess.

    – egreg
    Jun 5 at 9:12











  • Thank you, it is more a general question about the purpose of this expansion type. Under which circumstances would I want to use f instead of x or e expansion?

    – AlexG
    Jun 5 at 9:15






  • 1





    it is a thin wrapper around romannumeral with e now available it is possibly less useful than it was, but advantage over x that it can be used in expansion contexts

    – David Carlisle
    Jun 5 at 10:13


















  • f-type expansion ends with the first-encountered unexpandable token. If this token is a space, it is gobbled. You want e-type expansion, I guess.

    – egreg
    Jun 5 at 9:12











  • Thank you, it is more a general question about the purpose of this expansion type. Under which circumstances would I want to use f instead of x or e expansion?

    – AlexG
    Jun 5 at 9:15






  • 1





    it is a thin wrapper around romannumeral with e now available it is possibly less useful than it was, but advantage over x that it can be used in expansion contexts

    – David Carlisle
    Jun 5 at 10:13

















f-type expansion ends with the first-encountered unexpandable token. If this token is a space, it is gobbled. You want e-type expansion, I guess.

– egreg
Jun 5 at 9:12





f-type expansion ends with the first-encountered unexpandable token. If this token is a space, it is gobbled. You want e-type expansion, I guess.

– egreg
Jun 5 at 9:12













Thank you, it is more a general question about the purpose of this expansion type. Under which circumstances would I want to use f instead of x or e expansion?

– AlexG
Jun 5 at 9:15





Thank you, it is more a general question about the purpose of this expansion type. Under which circumstances would I want to use f instead of x or e expansion?

– AlexG
Jun 5 at 9:15




1




1





it is a thin wrapper around romannumeral with e now available it is possibly less useful than it was, but advantage over x that it can be used in expansion contexts

– David Carlisle
Jun 5 at 10:13






it is a thin wrapper around romannumeral with e now available it is possibly less useful than it was, but advantage over x that it can be used in expansion contexts

– David Carlisle
Jun 5 at 10:13











3 Answers
3






active

oldest

votes


















11














f-type expansion ends upon finding an unexpandable token; if this token is a space (character code 32, category code 10) it is gobbled.



Your tl_set:Nf l_mya_tl l_mya_tll_myb_tl will first do recursive expansion of l_mya_tl, leading to A. This is unexpandable, so the business stops here. The token list to assign is evaluated to Al_myb_tl and l_mya_tl is updated to contain this list.



Changing the contents of l_myb_tl will also change the expansion of l_mya_tl, because this one contains a pointer to l_myb_tl, rather than the value this variable had at definition time.



If you want to freeze the value of the updated l_mya_tl variable to the values of l_mya_tl and l_myb_tl you have to use either x-type or e-type expansion.



These last two types lead to the same result, but with a big difference: e-type expansion can appear in expansion contexts, x-type cannot. Not so much of a difference in this case, because you're doing an assignment. Actually, there is no predefined tl_set:Ne function, because it turns out that tl_set:Ne would take twice as much time as needed by tl_set:Nx.



documentclassarticle
usepackageexpl3,l3benchmark

ExplSyntaxOn

tl_set:Nn l_tmpa_tl A
tl_set:Nn l_tmpb_tl B
tl_new:N l_tmpc_tl
cs_generate_variant:Nn tl_set:Nn Ne

benchmark:n tl_set:Nx l_tmpc_tl l_tmpa_tl l_tmpb_tl

benchmark:n tl_set:Ne l_tmpc_tl l_tmpa_tl l_tmpb_tl

stop


yields, on my machine,



3.16e-7 seconds (1.01 ops)
7.78e-7 seconds (2.39 ops)


In either case, l_tmpc_tl is assigned AB.



Why would someone want f-expansion? Good question! Until a few months ago, there was no way to do full recursive expansion in expansion contexts. Things changed when the primitive expanded was added to all engines (it used to be allowed only in LuaTeX), except Knuth TeX, of course.






share|improve this answer























  • I do agree with OP that "full expansion" is rather misleading in this context. Would it not be better to change that to "expansion up to first obstacle" and claim that the f stands for "first"?

    – schtandard
    Jun 5 at 9:42











  • @schtandard Possibly.

    – egreg
    Jun 5 at 9:51











  • @schtandard I thought about that several times. To defend the “full”, I'd say that with “first”, one might understand that it acts as o, i.e., does only one expansion step. So, f-expansion is full expansion (read: recursive), but unlike that made by edef, stops at the first non-expandable token (+ gobbles it if it's a space token). f could mean “front” too. :-)

    – frougon
    Jun 5 at 9:59







  • 1





    Perhaps see tex.stackexchange.com/q/489063 on the question of expanded versus romannumeral.

    – Joseph Wright
    Jun 5 at 10:32






  • 1





    @AlexG Better than that: functions marked with a red star in interface3.pdf (aka, “fully expandable functions”) are safe to use inside an x-type argument (but those with a hollow star are not good to use inside an f-type argument). This is what the bottom of page 4 of interface3.pdf says.

    – frougon
    Jun 5 at 14:14



















7














Compare is with x-expansion:



documentclassarticle
usepackageexpl3

begindocument
ExplSyntaxOn
tl_set:Nn l_mya_tl A
tl_set:Nn l_myb_tl B
tl_set:Nf l_myc_tl l_mya_tl STOP l_myb_tl
tl_show:N l_myc_tl

tl_set:Nx l_myc_tl l_mya_tl STOP l_myb_tl
tl_show:N l_myc_tl

ExplSyntaxOffenddocument


This will give



> l_myc_tl=ASTOPl_myb_tl .
<recently read> }

l.207 tl_show:N l_myc_tl

?
> l_myc_tl=ASTOPB.
<recently read> }

l.210 tl_show:N l_myc_tl





share|improve this answer























  • Thank you, @Ulrike. Thus, show is the wanted tool to display the content of a control sequence. How could l_mya_tl look like such that expansion continues?

    – AlexG
    Jun 5 at 9:31






  • 1





    @AlexG One easy case is if the result of recursively expanding l_mya_tl is empty. You can also use macros inside that don't “produce” any unexpandable content but still have desirable side effects, such as gobbling specific things further in the token list (cf. macros such as use_none:nnn).

    – frougon
    Jun 5 at 9:50


















6














As pointed out in the other answers and comments, f-expansion is implemented using romannumeral which was sometimes needed in expansion contexts before the expanded primitive was available. This answer also mentions two use cases where it might still be of use, namely expansion without a known end point and lookaheads of the next unexpandable token.



Additionally, I'd like to point out a common use case where it's even wrong to use, as it gives undesired results. This is based on the fact that, while x-expansion continues fully expanding tokens beyond the first unexpanable token, f-expansion is more eager in the case exp_not:n is used in the token stream.



If we look at the following examples, we see that expansion is the same when exp:not:N (noexpand) is used:



cs_set:Npn foo [FOO] 

tl_set:Nx l_tmpb_tl exp_not:N foo bar
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl exp_not:N foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo bar.

> l_tmpb_tl=foo bar.


On the other hand, using exp_not:n (unexpanded) gives different results:



tl_set:Nx l_tmpb_tl exp_not:n foo bar 
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl exp_not:n foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo bar.

> l_tmpb_tl=[FOO]bar.


This is especially important when dealing with parts of the contents of token list variables via the tl_head:, tl_tail:, tl_range: etc. functions. All those wrap their result in exp_not:n. f-expansion may seem appropriate here, but it's actually not:



tl_set:Nn l_tmpa_tl foo bar 
tl_set:Nx l_tmpb_tl tl_head:V l_tmpa_tl
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl tl_head:V l_tmpa_tl
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo .

> l_tmpb_tl=[FOO].



As pointed out by Phelype Oleinik, protected macros behave differently as well:



cs_new_protected:Npn protected_foo foo 

tl_set:Nx l_tmpb_tl protected_foo bar
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl protected_foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=protected_foo bar.

> l_tmpb_tl=[FOO]bar.





share|improve this answer

























  • f expansion is reserved for TeX connoisseurs, it seems. Especially the last result, the verbatim foo is counter-intuitive. Could it be used as a reverse operation to csname ... endcsname (getting a command sequence's name)?

    – AlexG
    Jun 6 at 7:08






  • 1





    Note that the expansion of foo was foo too. I changed it to [FOO] to avoid confusion. So it's not resulting in the macro name. The point is that it's expanding foo even though it is hidden in unexpanded.

    – siracusa
    Jun 6 at 7:46











  • Ok, thank you. It is perhaps beyond the question's scope, but would it be difficult to translate the last f-type expansion example into TeX? (To see what happens behind the scene.)

    – AlexG
    Jun 6 at 8:06











  • @AlexG There are a lot of low-level expl3 macros involved here, rewriting all them to TeX is no fun. But you can see what's going on in more detail when you add tracingmacros=1relax before those lines. Each macro expansion is then written to the log file along with its current parameter values. In essence it's edefl_tmpa_tlunexpandedfoobar showl_tmpa_tl (x-expansion) vs. expandafterdefexpandafterl_tmpa_tlexpandafterromannumeral-0unexpandedfoobar showl_tmpa_tl (f-expansion).

    – siracusa
    Jun 6 at 8:28












  • Ah I see. This infamous romannumeral trick is involved. Thank you!

    – AlexG
    Jun 6 at 10:25













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
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f494280%2ff-type-expansion%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









11














f-type expansion ends upon finding an unexpandable token; if this token is a space (character code 32, category code 10) it is gobbled.



Your tl_set:Nf l_mya_tl l_mya_tll_myb_tl will first do recursive expansion of l_mya_tl, leading to A. This is unexpandable, so the business stops here. The token list to assign is evaluated to Al_myb_tl and l_mya_tl is updated to contain this list.



Changing the contents of l_myb_tl will also change the expansion of l_mya_tl, because this one contains a pointer to l_myb_tl, rather than the value this variable had at definition time.



If you want to freeze the value of the updated l_mya_tl variable to the values of l_mya_tl and l_myb_tl you have to use either x-type or e-type expansion.



These last two types lead to the same result, but with a big difference: e-type expansion can appear in expansion contexts, x-type cannot. Not so much of a difference in this case, because you're doing an assignment. Actually, there is no predefined tl_set:Ne function, because it turns out that tl_set:Ne would take twice as much time as needed by tl_set:Nx.



documentclassarticle
usepackageexpl3,l3benchmark

ExplSyntaxOn

tl_set:Nn l_tmpa_tl A
tl_set:Nn l_tmpb_tl B
tl_new:N l_tmpc_tl
cs_generate_variant:Nn tl_set:Nn Ne

benchmark:n tl_set:Nx l_tmpc_tl l_tmpa_tl l_tmpb_tl

benchmark:n tl_set:Ne l_tmpc_tl l_tmpa_tl l_tmpb_tl

stop


yields, on my machine,



3.16e-7 seconds (1.01 ops)
7.78e-7 seconds (2.39 ops)


In either case, l_tmpc_tl is assigned AB.



Why would someone want f-expansion? Good question! Until a few months ago, there was no way to do full recursive expansion in expansion contexts. Things changed when the primitive expanded was added to all engines (it used to be allowed only in LuaTeX), except Knuth TeX, of course.






share|improve this answer























  • I do agree with OP that "full expansion" is rather misleading in this context. Would it not be better to change that to "expansion up to first obstacle" and claim that the f stands for "first"?

    – schtandard
    Jun 5 at 9:42











  • @schtandard Possibly.

    – egreg
    Jun 5 at 9:51











  • @schtandard I thought about that several times. To defend the “full”, I'd say that with “first”, one might understand that it acts as o, i.e., does only one expansion step. So, f-expansion is full expansion (read: recursive), but unlike that made by edef, stops at the first non-expandable token (+ gobbles it if it's a space token). f could mean “front” too. :-)

    – frougon
    Jun 5 at 9:59







  • 1





    Perhaps see tex.stackexchange.com/q/489063 on the question of expanded versus romannumeral.

    – Joseph Wright
    Jun 5 at 10:32






  • 1





    @AlexG Better than that: functions marked with a red star in interface3.pdf (aka, “fully expandable functions”) are safe to use inside an x-type argument (but those with a hollow star are not good to use inside an f-type argument). This is what the bottom of page 4 of interface3.pdf says.

    – frougon
    Jun 5 at 14:14
















11














f-type expansion ends upon finding an unexpandable token; if this token is a space (character code 32, category code 10) it is gobbled.



Your tl_set:Nf l_mya_tl l_mya_tll_myb_tl will first do recursive expansion of l_mya_tl, leading to A. This is unexpandable, so the business stops here. The token list to assign is evaluated to Al_myb_tl and l_mya_tl is updated to contain this list.



Changing the contents of l_myb_tl will also change the expansion of l_mya_tl, because this one contains a pointer to l_myb_tl, rather than the value this variable had at definition time.



If you want to freeze the value of the updated l_mya_tl variable to the values of l_mya_tl and l_myb_tl you have to use either x-type or e-type expansion.



These last two types lead to the same result, but with a big difference: e-type expansion can appear in expansion contexts, x-type cannot. Not so much of a difference in this case, because you're doing an assignment. Actually, there is no predefined tl_set:Ne function, because it turns out that tl_set:Ne would take twice as much time as needed by tl_set:Nx.



documentclassarticle
usepackageexpl3,l3benchmark

ExplSyntaxOn

tl_set:Nn l_tmpa_tl A
tl_set:Nn l_tmpb_tl B
tl_new:N l_tmpc_tl
cs_generate_variant:Nn tl_set:Nn Ne

benchmark:n tl_set:Nx l_tmpc_tl l_tmpa_tl l_tmpb_tl

benchmark:n tl_set:Ne l_tmpc_tl l_tmpa_tl l_tmpb_tl

stop


yields, on my machine,



3.16e-7 seconds (1.01 ops)
7.78e-7 seconds (2.39 ops)


In either case, l_tmpc_tl is assigned AB.



Why would someone want f-expansion? Good question! Until a few months ago, there was no way to do full recursive expansion in expansion contexts. Things changed when the primitive expanded was added to all engines (it used to be allowed only in LuaTeX), except Knuth TeX, of course.






share|improve this answer























  • I do agree with OP that "full expansion" is rather misleading in this context. Would it not be better to change that to "expansion up to first obstacle" and claim that the f stands for "first"?

    – schtandard
    Jun 5 at 9:42











  • @schtandard Possibly.

    – egreg
    Jun 5 at 9:51











  • @schtandard I thought about that several times. To defend the “full”, I'd say that with “first”, one might understand that it acts as o, i.e., does only one expansion step. So, f-expansion is full expansion (read: recursive), but unlike that made by edef, stops at the first non-expandable token (+ gobbles it if it's a space token). f could mean “front” too. :-)

    – frougon
    Jun 5 at 9:59







  • 1





    Perhaps see tex.stackexchange.com/q/489063 on the question of expanded versus romannumeral.

    – Joseph Wright
    Jun 5 at 10:32






  • 1





    @AlexG Better than that: functions marked with a red star in interface3.pdf (aka, “fully expandable functions”) are safe to use inside an x-type argument (but those with a hollow star are not good to use inside an f-type argument). This is what the bottom of page 4 of interface3.pdf says.

    – frougon
    Jun 5 at 14:14














11












11








11







f-type expansion ends upon finding an unexpandable token; if this token is a space (character code 32, category code 10) it is gobbled.



Your tl_set:Nf l_mya_tl l_mya_tll_myb_tl will first do recursive expansion of l_mya_tl, leading to A. This is unexpandable, so the business stops here. The token list to assign is evaluated to Al_myb_tl and l_mya_tl is updated to contain this list.



Changing the contents of l_myb_tl will also change the expansion of l_mya_tl, because this one contains a pointer to l_myb_tl, rather than the value this variable had at definition time.



If you want to freeze the value of the updated l_mya_tl variable to the values of l_mya_tl and l_myb_tl you have to use either x-type or e-type expansion.



These last two types lead to the same result, but with a big difference: e-type expansion can appear in expansion contexts, x-type cannot. Not so much of a difference in this case, because you're doing an assignment. Actually, there is no predefined tl_set:Ne function, because it turns out that tl_set:Ne would take twice as much time as needed by tl_set:Nx.



documentclassarticle
usepackageexpl3,l3benchmark

ExplSyntaxOn

tl_set:Nn l_tmpa_tl A
tl_set:Nn l_tmpb_tl B
tl_new:N l_tmpc_tl
cs_generate_variant:Nn tl_set:Nn Ne

benchmark:n tl_set:Nx l_tmpc_tl l_tmpa_tl l_tmpb_tl

benchmark:n tl_set:Ne l_tmpc_tl l_tmpa_tl l_tmpb_tl

stop


yields, on my machine,



3.16e-7 seconds (1.01 ops)
7.78e-7 seconds (2.39 ops)


In either case, l_tmpc_tl is assigned AB.



Why would someone want f-expansion? Good question! Until a few months ago, there was no way to do full recursive expansion in expansion contexts. Things changed when the primitive expanded was added to all engines (it used to be allowed only in LuaTeX), except Knuth TeX, of course.






share|improve this answer













f-type expansion ends upon finding an unexpandable token; if this token is a space (character code 32, category code 10) it is gobbled.



Your tl_set:Nf l_mya_tl l_mya_tll_myb_tl will first do recursive expansion of l_mya_tl, leading to A. This is unexpandable, so the business stops here. The token list to assign is evaluated to Al_myb_tl and l_mya_tl is updated to contain this list.



Changing the contents of l_myb_tl will also change the expansion of l_mya_tl, because this one contains a pointer to l_myb_tl, rather than the value this variable had at definition time.



If you want to freeze the value of the updated l_mya_tl variable to the values of l_mya_tl and l_myb_tl you have to use either x-type or e-type expansion.



These last two types lead to the same result, but with a big difference: e-type expansion can appear in expansion contexts, x-type cannot. Not so much of a difference in this case, because you're doing an assignment. Actually, there is no predefined tl_set:Ne function, because it turns out that tl_set:Ne would take twice as much time as needed by tl_set:Nx.



documentclassarticle
usepackageexpl3,l3benchmark

ExplSyntaxOn

tl_set:Nn l_tmpa_tl A
tl_set:Nn l_tmpb_tl B
tl_new:N l_tmpc_tl
cs_generate_variant:Nn tl_set:Nn Ne

benchmark:n tl_set:Nx l_tmpc_tl l_tmpa_tl l_tmpb_tl

benchmark:n tl_set:Ne l_tmpc_tl l_tmpa_tl l_tmpb_tl

stop


yields, on my machine,



3.16e-7 seconds (1.01 ops)
7.78e-7 seconds (2.39 ops)


In either case, l_tmpc_tl is assigned AB.



Why would someone want f-expansion? Good question! Until a few months ago, there was no way to do full recursive expansion in expansion contexts. Things changed when the primitive expanded was added to all engines (it used to be allowed only in LuaTeX), except Knuth TeX, of course.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jun 5 at 9:33









egregegreg

749k8919623303




749k8919623303












  • I do agree with OP that "full expansion" is rather misleading in this context. Would it not be better to change that to "expansion up to first obstacle" and claim that the f stands for "first"?

    – schtandard
    Jun 5 at 9:42











  • @schtandard Possibly.

    – egreg
    Jun 5 at 9:51











  • @schtandard I thought about that several times. To defend the “full”, I'd say that with “first”, one might understand that it acts as o, i.e., does only one expansion step. So, f-expansion is full expansion (read: recursive), but unlike that made by edef, stops at the first non-expandable token (+ gobbles it if it's a space token). f could mean “front” too. :-)

    – frougon
    Jun 5 at 9:59







  • 1





    Perhaps see tex.stackexchange.com/q/489063 on the question of expanded versus romannumeral.

    – Joseph Wright
    Jun 5 at 10:32






  • 1





    @AlexG Better than that: functions marked with a red star in interface3.pdf (aka, “fully expandable functions”) are safe to use inside an x-type argument (but those with a hollow star are not good to use inside an f-type argument). This is what the bottom of page 4 of interface3.pdf says.

    – frougon
    Jun 5 at 14:14


















  • I do agree with OP that "full expansion" is rather misleading in this context. Would it not be better to change that to "expansion up to first obstacle" and claim that the f stands for "first"?

    – schtandard
    Jun 5 at 9:42











  • @schtandard Possibly.

    – egreg
    Jun 5 at 9:51











  • @schtandard I thought about that several times. To defend the “full”, I'd say that with “first”, one might understand that it acts as o, i.e., does only one expansion step. So, f-expansion is full expansion (read: recursive), but unlike that made by edef, stops at the first non-expandable token (+ gobbles it if it's a space token). f could mean “front” too. :-)

    – frougon
    Jun 5 at 9:59







  • 1





    Perhaps see tex.stackexchange.com/q/489063 on the question of expanded versus romannumeral.

    – Joseph Wright
    Jun 5 at 10:32






  • 1





    @AlexG Better than that: functions marked with a red star in interface3.pdf (aka, “fully expandable functions”) are safe to use inside an x-type argument (but those with a hollow star are not good to use inside an f-type argument). This is what the bottom of page 4 of interface3.pdf says.

    – frougon
    Jun 5 at 14:14

















I do agree with OP that "full expansion" is rather misleading in this context. Would it not be better to change that to "expansion up to first obstacle" and claim that the f stands for "first"?

– schtandard
Jun 5 at 9:42





I do agree with OP that "full expansion" is rather misleading in this context. Would it not be better to change that to "expansion up to first obstacle" and claim that the f stands for "first"?

– schtandard
Jun 5 at 9:42













@schtandard Possibly.

– egreg
Jun 5 at 9:51





@schtandard Possibly.

– egreg
Jun 5 at 9:51













@schtandard I thought about that several times. To defend the “full”, I'd say that with “first”, one might understand that it acts as o, i.e., does only one expansion step. So, f-expansion is full expansion (read: recursive), but unlike that made by edef, stops at the first non-expandable token (+ gobbles it if it's a space token). f could mean “front” too. :-)

– frougon
Jun 5 at 9:59






@schtandard I thought about that several times. To defend the “full”, I'd say that with “first”, one might understand that it acts as o, i.e., does only one expansion step. So, f-expansion is full expansion (read: recursive), but unlike that made by edef, stops at the first non-expandable token (+ gobbles it if it's a space token). f could mean “front” too. :-)

– frougon
Jun 5 at 9:59





1




1





Perhaps see tex.stackexchange.com/q/489063 on the question of expanded versus romannumeral.

– Joseph Wright
Jun 5 at 10:32





Perhaps see tex.stackexchange.com/q/489063 on the question of expanded versus romannumeral.

– Joseph Wright
Jun 5 at 10:32




1




1





@AlexG Better than that: functions marked with a red star in interface3.pdf (aka, “fully expandable functions”) are safe to use inside an x-type argument (but those with a hollow star are not good to use inside an f-type argument). This is what the bottom of page 4 of interface3.pdf says.

– frougon
Jun 5 at 14:14






@AlexG Better than that: functions marked with a red star in interface3.pdf (aka, “fully expandable functions”) are safe to use inside an x-type argument (but those with a hollow star are not good to use inside an f-type argument). This is what the bottom of page 4 of interface3.pdf says.

– frougon
Jun 5 at 14:14














7














Compare is with x-expansion:



documentclassarticle
usepackageexpl3

begindocument
ExplSyntaxOn
tl_set:Nn l_mya_tl A
tl_set:Nn l_myb_tl B
tl_set:Nf l_myc_tl l_mya_tl STOP l_myb_tl
tl_show:N l_myc_tl

tl_set:Nx l_myc_tl l_mya_tl STOP l_myb_tl
tl_show:N l_myc_tl

ExplSyntaxOffenddocument


This will give



> l_myc_tl=ASTOPl_myb_tl .
<recently read> }

l.207 tl_show:N l_myc_tl

?
> l_myc_tl=ASTOPB.
<recently read> }

l.210 tl_show:N l_myc_tl





share|improve this answer























  • Thank you, @Ulrike. Thus, show is the wanted tool to display the content of a control sequence. How could l_mya_tl look like such that expansion continues?

    – AlexG
    Jun 5 at 9:31






  • 1





    @AlexG One easy case is if the result of recursively expanding l_mya_tl is empty. You can also use macros inside that don't “produce” any unexpandable content but still have desirable side effects, such as gobbling specific things further in the token list (cf. macros such as use_none:nnn).

    – frougon
    Jun 5 at 9:50















7














Compare is with x-expansion:



documentclassarticle
usepackageexpl3

begindocument
ExplSyntaxOn
tl_set:Nn l_mya_tl A
tl_set:Nn l_myb_tl B
tl_set:Nf l_myc_tl l_mya_tl STOP l_myb_tl
tl_show:N l_myc_tl

tl_set:Nx l_myc_tl l_mya_tl STOP l_myb_tl
tl_show:N l_myc_tl

ExplSyntaxOffenddocument


This will give



> l_myc_tl=ASTOPl_myb_tl .
<recently read> }

l.207 tl_show:N l_myc_tl

?
> l_myc_tl=ASTOPB.
<recently read> }

l.210 tl_show:N l_myc_tl





share|improve this answer























  • Thank you, @Ulrike. Thus, show is the wanted tool to display the content of a control sequence. How could l_mya_tl look like such that expansion continues?

    – AlexG
    Jun 5 at 9:31






  • 1





    @AlexG One easy case is if the result of recursively expanding l_mya_tl is empty. You can also use macros inside that don't “produce” any unexpandable content but still have desirable side effects, such as gobbling specific things further in the token list (cf. macros such as use_none:nnn).

    – frougon
    Jun 5 at 9:50













7












7








7







Compare is with x-expansion:



documentclassarticle
usepackageexpl3

begindocument
ExplSyntaxOn
tl_set:Nn l_mya_tl A
tl_set:Nn l_myb_tl B
tl_set:Nf l_myc_tl l_mya_tl STOP l_myb_tl
tl_show:N l_myc_tl

tl_set:Nx l_myc_tl l_mya_tl STOP l_myb_tl
tl_show:N l_myc_tl

ExplSyntaxOffenddocument


This will give



> l_myc_tl=ASTOPl_myb_tl .
<recently read> }

l.207 tl_show:N l_myc_tl

?
> l_myc_tl=ASTOPB.
<recently read> }

l.210 tl_show:N l_myc_tl





share|improve this answer













Compare is with x-expansion:



documentclassarticle
usepackageexpl3

begindocument
ExplSyntaxOn
tl_set:Nn l_mya_tl A
tl_set:Nn l_myb_tl B
tl_set:Nf l_myc_tl l_mya_tl STOP l_myb_tl
tl_show:N l_myc_tl

tl_set:Nx l_myc_tl l_mya_tl STOP l_myb_tl
tl_show:N l_myc_tl

ExplSyntaxOffenddocument


This will give



> l_myc_tl=ASTOPl_myb_tl .
<recently read> }

l.207 tl_show:N l_myc_tl

?
> l_myc_tl=ASTOPB.
<recently read> }

l.210 tl_show:N l_myc_tl






share|improve this answer












share|improve this answer



share|improve this answer










answered Jun 5 at 9:22









Ulrike FischerUlrike Fischer

206k9314706




206k9314706












  • Thank you, @Ulrike. Thus, show is the wanted tool to display the content of a control sequence. How could l_mya_tl look like such that expansion continues?

    – AlexG
    Jun 5 at 9:31






  • 1





    @AlexG One easy case is if the result of recursively expanding l_mya_tl is empty. You can also use macros inside that don't “produce” any unexpandable content but still have desirable side effects, such as gobbling specific things further in the token list (cf. macros such as use_none:nnn).

    – frougon
    Jun 5 at 9:50

















  • Thank you, @Ulrike. Thus, show is the wanted tool to display the content of a control sequence. How could l_mya_tl look like such that expansion continues?

    – AlexG
    Jun 5 at 9:31






  • 1





    @AlexG One easy case is if the result of recursively expanding l_mya_tl is empty. You can also use macros inside that don't “produce” any unexpandable content but still have desirable side effects, such as gobbling specific things further in the token list (cf. macros such as use_none:nnn).

    – frougon
    Jun 5 at 9:50
















Thank you, @Ulrike. Thus, show is the wanted tool to display the content of a control sequence. How could l_mya_tl look like such that expansion continues?

– AlexG
Jun 5 at 9:31





Thank you, @Ulrike. Thus, show is the wanted tool to display the content of a control sequence. How could l_mya_tl look like such that expansion continues?

– AlexG
Jun 5 at 9:31




1




1





@AlexG One easy case is if the result of recursively expanding l_mya_tl is empty. You can also use macros inside that don't “produce” any unexpandable content but still have desirable side effects, such as gobbling specific things further in the token list (cf. macros such as use_none:nnn).

– frougon
Jun 5 at 9:50





@AlexG One easy case is if the result of recursively expanding l_mya_tl is empty. You can also use macros inside that don't “produce” any unexpandable content but still have desirable side effects, such as gobbling specific things further in the token list (cf. macros such as use_none:nnn).

– frougon
Jun 5 at 9:50











6














As pointed out in the other answers and comments, f-expansion is implemented using romannumeral which was sometimes needed in expansion contexts before the expanded primitive was available. This answer also mentions two use cases where it might still be of use, namely expansion without a known end point and lookaheads of the next unexpandable token.



Additionally, I'd like to point out a common use case where it's even wrong to use, as it gives undesired results. This is based on the fact that, while x-expansion continues fully expanding tokens beyond the first unexpanable token, f-expansion is more eager in the case exp_not:n is used in the token stream.



If we look at the following examples, we see that expansion is the same when exp:not:N (noexpand) is used:



cs_set:Npn foo [FOO] 

tl_set:Nx l_tmpb_tl exp_not:N foo bar
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl exp_not:N foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo bar.

> l_tmpb_tl=foo bar.


On the other hand, using exp_not:n (unexpanded) gives different results:



tl_set:Nx l_tmpb_tl exp_not:n foo bar 
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl exp_not:n foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo bar.

> l_tmpb_tl=[FOO]bar.


This is especially important when dealing with parts of the contents of token list variables via the tl_head:, tl_tail:, tl_range: etc. functions. All those wrap their result in exp_not:n. f-expansion may seem appropriate here, but it's actually not:



tl_set:Nn l_tmpa_tl foo bar 
tl_set:Nx l_tmpb_tl tl_head:V l_tmpa_tl
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl tl_head:V l_tmpa_tl
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo .

> l_tmpb_tl=[FOO].



As pointed out by Phelype Oleinik, protected macros behave differently as well:



cs_new_protected:Npn protected_foo foo 

tl_set:Nx l_tmpb_tl protected_foo bar
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl protected_foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=protected_foo bar.

> l_tmpb_tl=[FOO]bar.





share|improve this answer

























  • f expansion is reserved for TeX connoisseurs, it seems. Especially the last result, the verbatim foo is counter-intuitive. Could it be used as a reverse operation to csname ... endcsname (getting a command sequence's name)?

    – AlexG
    Jun 6 at 7:08






  • 1





    Note that the expansion of foo was foo too. I changed it to [FOO] to avoid confusion. So it's not resulting in the macro name. The point is that it's expanding foo even though it is hidden in unexpanded.

    – siracusa
    Jun 6 at 7:46











  • Ok, thank you. It is perhaps beyond the question's scope, but would it be difficult to translate the last f-type expansion example into TeX? (To see what happens behind the scene.)

    – AlexG
    Jun 6 at 8:06











  • @AlexG There are a lot of low-level expl3 macros involved here, rewriting all them to TeX is no fun. But you can see what's going on in more detail when you add tracingmacros=1relax before those lines. Each macro expansion is then written to the log file along with its current parameter values. In essence it's edefl_tmpa_tlunexpandedfoobar showl_tmpa_tl (x-expansion) vs. expandafterdefexpandafterl_tmpa_tlexpandafterromannumeral-0unexpandedfoobar showl_tmpa_tl (f-expansion).

    – siracusa
    Jun 6 at 8:28












  • Ah I see. This infamous romannumeral trick is involved. Thank you!

    – AlexG
    Jun 6 at 10:25















6














As pointed out in the other answers and comments, f-expansion is implemented using romannumeral which was sometimes needed in expansion contexts before the expanded primitive was available. This answer also mentions two use cases where it might still be of use, namely expansion without a known end point and lookaheads of the next unexpandable token.



Additionally, I'd like to point out a common use case where it's even wrong to use, as it gives undesired results. This is based on the fact that, while x-expansion continues fully expanding tokens beyond the first unexpanable token, f-expansion is more eager in the case exp_not:n is used in the token stream.



If we look at the following examples, we see that expansion is the same when exp:not:N (noexpand) is used:



cs_set:Npn foo [FOO] 

tl_set:Nx l_tmpb_tl exp_not:N foo bar
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl exp_not:N foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo bar.

> l_tmpb_tl=foo bar.


On the other hand, using exp_not:n (unexpanded) gives different results:



tl_set:Nx l_tmpb_tl exp_not:n foo bar 
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl exp_not:n foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo bar.

> l_tmpb_tl=[FOO]bar.


This is especially important when dealing with parts of the contents of token list variables via the tl_head:, tl_tail:, tl_range: etc. functions. All those wrap their result in exp_not:n. f-expansion may seem appropriate here, but it's actually not:



tl_set:Nn l_tmpa_tl foo bar 
tl_set:Nx l_tmpb_tl tl_head:V l_tmpa_tl
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl tl_head:V l_tmpa_tl
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo .

> l_tmpb_tl=[FOO].



As pointed out by Phelype Oleinik, protected macros behave differently as well:



cs_new_protected:Npn protected_foo foo 

tl_set:Nx l_tmpb_tl protected_foo bar
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl protected_foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=protected_foo bar.

> l_tmpb_tl=[FOO]bar.





share|improve this answer

























  • f expansion is reserved for TeX connoisseurs, it seems. Especially the last result, the verbatim foo is counter-intuitive. Could it be used as a reverse operation to csname ... endcsname (getting a command sequence's name)?

    – AlexG
    Jun 6 at 7:08






  • 1





    Note that the expansion of foo was foo too. I changed it to [FOO] to avoid confusion. So it's not resulting in the macro name. The point is that it's expanding foo even though it is hidden in unexpanded.

    – siracusa
    Jun 6 at 7:46











  • Ok, thank you. It is perhaps beyond the question's scope, but would it be difficult to translate the last f-type expansion example into TeX? (To see what happens behind the scene.)

    – AlexG
    Jun 6 at 8:06











  • @AlexG There are a lot of low-level expl3 macros involved here, rewriting all them to TeX is no fun. But you can see what's going on in more detail when you add tracingmacros=1relax before those lines. Each macro expansion is then written to the log file along with its current parameter values. In essence it's edefl_tmpa_tlunexpandedfoobar showl_tmpa_tl (x-expansion) vs. expandafterdefexpandafterl_tmpa_tlexpandafterromannumeral-0unexpandedfoobar showl_tmpa_tl (f-expansion).

    – siracusa
    Jun 6 at 8:28












  • Ah I see. This infamous romannumeral trick is involved. Thank you!

    – AlexG
    Jun 6 at 10:25













6












6








6







As pointed out in the other answers and comments, f-expansion is implemented using romannumeral which was sometimes needed in expansion contexts before the expanded primitive was available. This answer also mentions two use cases where it might still be of use, namely expansion without a known end point and lookaheads of the next unexpandable token.



Additionally, I'd like to point out a common use case where it's even wrong to use, as it gives undesired results. This is based on the fact that, while x-expansion continues fully expanding tokens beyond the first unexpanable token, f-expansion is more eager in the case exp_not:n is used in the token stream.



If we look at the following examples, we see that expansion is the same when exp:not:N (noexpand) is used:



cs_set:Npn foo [FOO] 

tl_set:Nx l_tmpb_tl exp_not:N foo bar
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl exp_not:N foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo bar.

> l_tmpb_tl=foo bar.


On the other hand, using exp_not:n (unexpanded) gives different results:



tl_set:Nx l_tmpb_tl exp_not:n foo bar 
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl exp_not:n foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo bar.

> l_tmpb_tl=[FOO]bar.


This is especially important when dealing with parts of the contents of token list variables via the tl_head:, tl_tail:, tl_range: etc. functions. All those wrap their result in exp_not:n. f-expansion may seem appropriate here, but it's actually not:



tl_set:Nn l_tmpa_tl foo bar 
tl_set:Nx l_tmpb_tl tl_head:V l_tmpa_tl
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl tl_head:V l_tmpa_tl
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo .

> l_tmpb_tl=[FOO].



As pointed out by Phelype Oleinik, protected macros behave differently as well:



cs_new_protected:Npn protected_foo foo 

tl_set:Nx l_tmpb_tl protected_foo bar
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl protected_foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=protected_foo bar.

> l_tmpb_tl=[FOO]bar.





share|improve this answer















As pointed out in the other answers and comments, f-expansion is implemented using romannumeral which was sometimes needed in expansion contexts before the expanded primitive was available. This answer also mentions two use cases where it might still be of use, namely expansion without a known end point and lookaheads of the next unexpandable token.



Additionally, I'd like to point out a common use case where it's even wrong to use, as it gives undesired results. This is based on the fact that, while x-expansion continues fully expanding tokens beyond the first unexpanable token, f-expansion is more eager in the case exp_not:n is used in the token stream.



If we look at the following examples, we see that expansion is the same when exp:not:N (noexpand) is used:



cs_set:Npn foo [FOO] 

tl_set:Nx l_tmpb_tl exp_not:N foo bar
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl exp_not:N foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo bar.

> l_tmpb_tl=foo bar.


On the other hand, using exp_not:n (unexpanded) gives different results:



tl_set:Nx l_tmpb_tl exp_not:n foo bar 
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl exp_not:n foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo bar.

> l_tmpb_tl=[FOO]bar.


This is especially important when dealing with parts of the contents of token list variables via the tl_head:, tl_tail:, tl_range: etc. functions. All those wrap their result in exp_not:n. f-expansion may seem appropriate here, but it's actually not:



tl_set:Nn l_tmpa_tl foo bar 
tl_set:Nx l_tmpb_tl tl_head:V l_tmpa_tl
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl tl_head:V l_tmpa_tl
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=foo .

> l_tmpb_tl=[FOO].



As pointed out by Phelype Oleinik, protected macros behave differently as well:



cs_new_protected:Npn protected_foo foo 

tl_set:Nx l_tmpb_tl protected_foo bar
tl_show:N l_tmpb_tl

tl_set:Nf l_tmpb_tl protected_foo bar
tl_show:N l_tmpb_tl


outputs



> l_tmpb_tl=protected_foo bar.

> l_tmpb_tl=[FOO]bar.






share|improve this answer














share|improve this answer



share|improve this answer








edited Jun 7 at 2:21

























answered Jun 6 at 5:49









siracusasiracusa

6,38911733




6,38911733












  • f expansion is reserved for TeX connoisseurs, it seems. Especially the last result, the verbatim foo is counter-intuitive. Could it be used as a reverse operation to csname ... endcsname (getting a command sequence's name)?

    – AlexG
    Jun 6 at 7:08






  • 1





    Note that the expansion of foo was foo too. I changed it to [FOO] to avoid confusion. So it's not resulting in the macro name. The point is that it's expanding foo even though it is hidden in unexpanded.

    – siracusa
    Jun 6 at 7:46











  • Ok, thank you. It is perhaps beyond the question's scope, but would it be difficult to translate the last f-type expansion example into TeX? (To see what happens behind the scene.)

    – AlexG
    Jun 6 at 8:06











  • @AlexG There are a lot of low-level expl3 macros involved here, rewriting all them to TeX is no fun. But you can see what's going on in more detail when you add tracingmacros=1relax before those lines. Each macro expansion is then written to the log file along with its current parameter values. In essence it's edefl_tmpa_tlunexpandedfoobar showl_tmpa_tl (x-expansion) vs. expandafterdefexpandafterl_tmpa_tlexpandafterromannumeral-0unexpandedfoobar showl_tmpa_tl (f-expansion).

    – siracusa
    Jun 6 at 8:28












  • Ah I see. This infamous romannumeral trick is involved. Thank you!

    – AlexG
    Jun 6 at 10:25

















  • f expansion is reserved for TeX connoisseurs, it seems. Especially the last result, the verbatim foo is counter-intuitive. Could it be used as a reverse operation to csname ... endcsname (getting a command sequence's name)?

    – AlexG
    Jun 6 at 7:08






  • 1





    Note that the expansion of foo was foo too. I changed it to [FOO] to avoid confusion. So it's not resulting in the macro name. The point is that it's expanding foo even though it is hidden in unexpanded.

    – siracusa
    Jun 6 at 7:46











  • Ok, thank you. It is perhaps beyond the question's scope, but would it be difficult to translate the last f-type expansion example into TeX? (To see what happens behind the scene.)

    – AlexG
    Jun 6 at 8:06











  • @AlexG There are a lot of low-level expl3 macros involved here, rewriting all them to TeX is no fun. But you can see what's going on in more detail when you add tracingmacros=1relax before those lines. Each macro expansion is then written to the log file along with its current parameter values. In essence it's edefl_tmpa_tlunexpandedfoobar showl_tmpa_tl (x-expansion) vs. expandafterdefexpandafterl_tmpa_tlexpandafterromannumeral-0unexpandedfoobar showl_tmpa_tl (f-expansion).

    – siracusa
    Jun 6 at 8:28












  • Ah I see. This infamous romannumeral trick is involved. Thank you!

    – AlexG
    Jun 6 at 10:25
















f expansion is reserved for TeX connoisseurs, it seems. Especially the last result, the verbatim foo is counter-intuitive. Could it be used as a reverse operation to csname ... endcsname (getting a command sequence's name)?

– AlexG
Jun 6 at 7:08





f expansion is reserved for TeX connoisseurs, it seems. Especially the last result, the verbatim foo is counter-intuitive. Could it be used as a reverse operation to csname ... endcsname (getting a command sequence's name)?

– AlexG
Jun 6 at 7:08




1




1





Note that the expansion of foo was foo too. I changed it to [FOO] to avoid confusion. So it's not resulting in the macro name. The point is that it's expanding foo even though it is hidden in unexpanded.

– siracusa
Jun 6 at 7:46





Note that the expansion of foo was foo too. I changed it to [FOO] to avoid confusion. So it's not resulting in the macro name. The point is that it's expanding foo even though it is hidden in unexpanded.

– siracusa
Jun 6 at 7:46













Ok, thank you. It is perhaps beyond the question's scope, but would it be difficult to translate the last f-type expansion example into TeX? (To see what happens behind the scene.)

– AlexG
Jun 6 at 8:06





Ok, thank you. It is perhaps beyond the question's scope, but would it be difficult to translate the last f-type expansion example into TeX? (To see what happens behind the scene.)

– AlexG
Jun 6 at 8:06













@AlexG There are a lot of low-level expl3 macros involved here, rewriting all them to TeX is no fun. But you can see what's going on in more detail when you add tracingmacros=1relax before those lines. Each macro expansion is then written to the log file along with its current parameter values. In essence it's edefl_tmpa_tlunexpandedfoobar showl_tmpa_tl (x-expansion) vs. expandafterdefexpandafterl_tmpa_tlexpandafterromannumeral-0unexpandedfoobar showl_tmpa_tl (f-expansion).

– siracusa
Jun 6 at 8:28






@AlexG There are a lot of low-level expl3 macros involved here, rewriting all them to TeX is no fun. But you can see what's going on in more detail when you add tracingmacros=1relax before those lines. Each macro expansion is then written to the log file along with its current parameter values. In essence it's edefl_tmpa_tlunexpandedfoobar showl_tmpa_tl (x-expansion) vs. expandafterdefexpandafterl_tmpa_tlexpandafterromannumeral-0unexpandedfoobar showl_tmpa_tl (f-expansion).

– siracusa
Jun 6 at 8:28














Ah I see. This infamous romannumeral trick is involved. Thank you!

– AlexG
Jun 6 at 10:25





Ah I see. This infamous romannumeral trick is involved. Thank you!

– AlexG
Jun 6 at 10:25

















draft saved

draft discarded
















































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.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f494280%2ff-type-expansion%23new-answer', 'question_page');

);

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







Popular posts from this blog

Wikipedia:Vital articles Мазмуну Biography - Өмүр баян Philosophy and psychology - Философия жана психология Religion - Дин Social sciences - Коомдук илимдер Language and literature - Тил жана адабият Science - Илим Technology - Технология Arts and recreation - Искусство жана эс алуу History and geography - Тарых жана география Навигация менюсу

Bruxelas-Capital Índice Historia | Composición | Situación lingüística | Clima | Cidades irmandadas | Notas | Véxase tamén | Menú de navegacióneO uso das linguas en Bruxelas e a situación do neerlandés"Rexión de Bruxelas Capital"o orixinalSitio da rexiónPáxina de Bruselas no sitio da Oficina de Promoción Turística de Valonia e BruxelasMapa Interactivo da Rexión de Bruxelas-CapitaleeWorldCat332144929079854441105155190212ID28008674080552-90000 0001 0666 3698n94104302ID540940339365017018237

What should I write in an apology letter, since I have decided not to join a company after accepting an offer letterShould I keep looking after accepting a job offer?What should I do when I've been verbally told I would get an offer letter, but still haven't gotten one after 4 weeks?Do I accept an offer from a company that I am not likely to join?New job hasn't confirmed starting date and I want to give current employer as much notice as possibleHow should I address my manager in my resignation letter?HR delayed background verification, now jobless as resignedNo email communication after accepting a formal written offer. How should I phrase the call?What should I do if after receiving a verbal offer letter I am informed that my written job offer is put on hold due to some internal issues?Should I inform the current employer that I am about to resign within 1-2 weeks since I have signed the offer letter and waiting for visa?What company will do, if I send their offer letter to another company