3

How to make \foo_bar: expand to code a?

\bool_new:N \foo_bool
\bool_set_true:N \foo_bool

\cs_new:Nn \foo_bar:
  {
    \bool_if:NTF \foo_bool
      { code~ a } { code~ b }
  }

update:

How about this one?

% `test.pdf` is in the current directory.
\cs_new:Nn \foo_bar:
  {
    \file_if_exist:nTF { test.pdf }
      { code~ a } { code~ b }
  }

(Complete question can be found in Expand condition functions in xeCJK)

10
  • Could you 'expand' your fragment into a compilable document first, please ;-), but it should be \cs_new_nopar:Nn \foo_bar: rather. But it expands to a for me
    – user31729
    Commented Jul 13, 2017 at 17:16
  • Use \cs_new:Nx (or define a variant \cs_new:Nf)
    – egreg
    Commented Jul 13, 2017 at 17:17
  • Sorry, changing the question and piling up new requests is not the way to react to answers ;-
    – user31729
    Commented Jul 13, 2017 at 17:39
  • Sorry for that... But the second one is actually what I need to do and I think both questions are interesting.
    – stone-zeng
    Commented Jul 13, 2017 at 17:45
  • \file_if_exist:nTF is not expandable. Commented Jul 13, 2017 at 19:02

2 Answers 2

2

If the conditional value of \foo_bool should be frozen (expanded) in the definition of the macro, \cs_new:Nx is one possibility, if the macro should 'react' on the current value of \foo_bool, use \cs_new:Nn here.

I've changed the names to 'proper' expl3 naming conventions.

\documentclass{book}

\usepackage{xparse}

\ExplSyntaxOn

\bool_new:N \l_stone_foo_bool
\bool_set_false:N \l_stone_foo_bool% Set to false, although false by def. 

\cs_new:Nn \foo_bar_current:
{
  \bool_if:NTF \l_stone_foo_bool
  { code~ a } { code~ b }
}

\cs_new:Nx \foo_bar_expanded:
{
  \bool_if:NTF \l_stone_foo_bool
  { code~ a } { code~ b }
}


\NewDocumentCommand{\foo}{}{%
  \foo_bar_expanded:
}

\NewDocumentCommand{\foobar}{}{%
  \foo_bar_current:
}

\bool_set_true:N \l_stone_foo_bool% For testing
\ExplSyntaxOff
\begin{document}
\foo\ and \foobar

\end{document}

\foo will expand to code b and \foobar will expand to code a, since setting the bool variable to true in the meantime, after defining \foobar.

enter image description here

5
  • 1
    FYI, we've moved away from encouraging _nopar use for argument-less macros because it adds things to think about with no benefit. In the core expl3 the only _nopar macros are user-facing ones or those that have to be compared to token lists. Commented Jul 13, 2017 at 19:01
  • @BrunoLeFloch: Eh, since which date you're encouraging users away from this? I was scolded two years ago, starting with expl3, for not using _nopar :-(
    – user31729
    Commented Jul 13, 2017 at 19:02
  • Sorry, we learn from experience. I have no idea when we changed. Commented Jul 13, 2017 at 19:04
  • @ChristianHupfer As Bruno says, we realised a while ago that other than for setting up xparse and for some limited internal place, using nopar didn't really help. (For document-level interfaces it's different.) So it's not wrong to use nopar, it's just that we wouldn't do it now. As Bruno says, this is the 'experimental' part of expl3: there are changes as new ideas come forward.
    – Joseph Wright
    Commented Jul 14, 2017 at 5:26
  • @JosephWright: Removed the _nopar 'modifier'...
    – user31729
    Commented Jul 17, 2017 at 20:51
1

I guess you are defining a function that depends on some runtime options. The solution is to use \cs_new:Nx (which internally uses \edef).

\documentclass{article}
\usepackage{expl3}

\ExplSyntaxOn

\bool_new:N \l_stonezeng_foo_bool

% true branch
\bool_set_true:N \l_stonezeng_foo_bool

\cs_new:Nx \stonezeng_foo_t:
 {
  \bool_if:NTF \l_stonezeng_foo_bool
   {
    \exp_not:n { code~a }
   }
   {
    \exp_not:n { code~b }
   }
 }

% false branch
\bool_set_false:N \l_stonezeng_foo_bool

\cs_new:Nx \stonezeng_foo_f:
 {
  \bool_if:NTF \l_stonezeng_foo_bool
   {
    \exp_not:n { code~a }
   }
   {
    \exp_not:n { code~b }
   }
 }

\cs_show:N \stonezeng_foo_t:
\cs_show:N \stonezeng_foo_f:

\stop

This will show on the terminal

> \stonezeng_foo_t:=\long macro:->code a.

> \stonezeng_foo_f:=\long macro:->code b.

Note \exp_not:n, so the inner code will not be expanded at definition time, but only upon usage.

Remember to use proper naming of variables and functions.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .