1

I want to define a command to receive an environment name list (and other argument to control the behavior of the environment, I remove them for simplify) and define these environments, but it does not behave as expected.

As Ulrike Fischer commented, I should pass ##1 to \__test:nnnn, but if \NewDocumentEnvironment is nested deeper, ####1, ########1 and so on are too long to use, is there any way to still use #1 to represent the argument of \NewDocumentEnvironment?

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected:Nn \__test:nnnn
  {
    \typeout{#3}% ##1
    \clist_map_inline:nn { #1 }
      {
        \typeout{#3}% 'a', 'b', 'c'
        \NewDocumentEnvironment { test##1 } { #2 }
          { #3 } { #4 }
      }
  }

\__test:nnnn { a, b, c } { m } { #1 } { }

% cause error
% Illegal parameter number in definition of \__clist_map_1:w.
% \__test:nnnn { e, f } { m +b } { #1 #2 } { }
\ExplSyntaxOff

\begin{document}
% output 'a' which should be 'test'
\begin{testa}{test}
\end{testa}
\end{document}
4
  • 1
    you need to call it with \__test:nnnn { a, b, c } { m } { ##1 } { }. But why are you defining three environments which all do the same thing? Sep 27, 2020 at 21:19
  • @UlrikeFischer For simplify, I remove the extra argument, they are just almost the same, is there a way to use #1 instead of ##1 ?
    – ZhiyuanLck
    Sep 28, 2020 at 2:59
  • @ZhiyuanLck Whatever you put in the fourth argument, you'll end up with three environments defined in exactly the same way. What's this useful for?
    – egreg
    Sep 28, 2020 at 10:24
  • @egreg I want to define a lot of similar environments that associate with a group name, and inside the environment there is a local command say \save to save some content in a sequence such as \g__save_<group_name>_<i'th group>_seq for later use. Cauze there will be multiple \save commands inside the environment, it is better to use \save instead of \save{<group name>}...
    – ZhiyuanLck
    Sep 28, 2020 at 10:31

1 Answer 1

1

I'm not sure how useful this is. Anyway, you can avoid doubling # in the third and fourth argument by storing the arguments is token list variables before doing the mapping.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected:Nn \__zhiyuan_test_defenv:nnnn
 {
  \tl_set:Nn \l__zhiyuan_scratch_a_tl { #3 }
  \tl_set:Nn \l__zhiyuan_scratch_b_tl { #4 }
  \clist_map_inline:nn { #1 }
   {
    \__zhiyuan_newenv:nnVV { ##1 } { #2 } \l__zhiyuan_scratch_a_tl \l__zhiyuan_scratch_b_tl
   }
 }
\cs_new_protected:Nn \__zhiyuan_newenv:nnnn
 {
  \NewDocumentEnvironment { test#1 } { #2 } { #3 } { #4 }
 }
\cs_generate_variant:Nn \__zhiyuan_newenv:nnnn { nnVV }

\__zhiyuan_test_defenv:nnnn { a, b, c } { m } { #1 } { }

\ExplSyntaxOff

\begin{document}
% output 'a' which should be 'test'
\begin{testa}{test}
\end{testa}
\end{document}
2
  • Wow, I have thought about this way, but I forgot to use a V signature. By the way, is there no need to put a \tl_clear_set:N <tl var> before a \tl_set:Nn <tl var>?
    – ZhiyuanLck
    Sep 28, 2020 at 10:38
  • @ZhiyuanLck There is no \tl_clear_set:N, but no need to do \tl_clear:N either: with \tl_set:Nn the possible contents of the variable is overwritten anyway.
    – egreg
    Sep 28, 2020 at 10:40

You must log in to answer this question.

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