From what you told us so far, one cannot reproduce the problem and therefore tracking down/tracing the source of the problem is, to some degree, associated with guesswork.
First some general remarks—I hope that my guesses are right and that my remarks are useful:
- At the time of gathering arguments for macros or environments from the token-stream, expansion is not triggered.
- In case it is present, (La)TeX will remove the outermost level of curly braces that surrounds an entire argument when inserting that argument into the replacement-text during expansion.
After "digging out" the ConcProg-class on CTAN (https://ctan.org/pkg/concprog), I found that the environment composition
processes four arguments:
- ⟨author⟩
- ⟨years of birth (and death)⟩
- ⟨title of the composition⟩
- ⟨optional description⟩
Thus with
\begin{composition}{Folk Song}{}{Twinkle Twinkle Little Star}{Student Name}
⟨whatsoever environment-body⟩
\end{composition}
- the first argument of the
composition
-environment will be: Folk Song
,
- the second argument of the
composition
-environment will be empty,
- the third argument of the
composition
-environment will be: Twinkle Twinkle Little Star
,
- the fourth argument of the
composition
-environment will be: Student Name
,
while with
\begin{composition}\twinkle\studentname
\end{composition}
- the first argument of the
composition
-environment will be: \twinkle
,
- the second argument of the
composition
-environment will be \studentname
,
- the third argument of the
composition
-environment will be: \end
,
- the fourth argument of the
composition
-environment will be: composition
.
This is because expansion is not triggered when LaTeX gathers arguments for macros or environments.
Depending on how the arguments get inserted when LaTeX carries out/expands the macros that underlie the composition
-environment, this way of fetching arguments may lead to all kinds of weird/erroneous/problematic behaviour.
I can offer a customized variant of the composition
-environment, called mycomposition
, which takes care of expansion:
Actually the environment does not process any arguments at all. Instead it checks whether the next token in its environment-body is expandable or not. If it is, expansion will take place until finding a non-expandable token. (Be aware that curly opening braces {
are not expandable tokens. ;-)) Then it will grab an argument. It does this four times for grabbing 4 arguments. Then internally it passes these four arguments to the macro underlying the composition
-environment:
\documentclass{ConcProg}
\makeatletter
\newcommand\UD@CheckWhetherNextExpandable[2]{%
\def\UD@reserved@a{#1}%
\def\UD@reserved@b{#2}%
\UD@@CheckWhetherNextExpandable
}%
\newcommand\UD@@CheckWhetherNextExpandable{%
\futurelet\UD@reserved@c\UD@@@CheckWhetherNextExpandable
}%
\newcommand\UD@@@CheckWhetherNextExpandable{%
\ifx\UD@reserved@c\@sptoken\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\afterassignment\UD@@CheckWhetherNextExpandable\let\UD@reserved@c= }%
{%
\expandafter\ifx\noexpand\UD@reserved@c\UD@reserved@c
\expandafter\UD@reserved@b
\else
\expandafter\UD@reserved@a
\fi
}%
}%
\newcommand\UD@ExpandUntilFirstUnexpandableAndAddToUD@reserved@d[1]{%
\ifx\relax#1\relax\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\expandafter\endgroup\UD@reserved@d}%
{\UD@CheckWhetherNextExpandable
{\expandafter\UD@@CheckWhetherNextExpandable}%
{\expandafter\UD@AddNextTo\expandafter{\@gobble#1}\UD@reserved@d}%
}%
}%
\newcommand\UD@AddNextTo[3]{%
% \edef..\the\toks@-route prevents halving of hashes.
\toks@\expandafter{#2{#3}}%
\edef#2{\the\toks@}%
\UD@ExpandUntilFirstUnexpandableAndAddToUD@reserved@d{#1}%
}%
\newcommand\UD@ExpandAndAccumulateKArgsAndPassTo[2]{%
\begingroup
\def\UD@reserved@d{#2}%
\expandafter\UD@ExpandUntilFirstUnexpandableAndAddToUD@reserved@d
\expandafter{\romannumeral\number\number#1 000}%
}%
\newenvironment{mycomposition}%
{\UD@ExpandAndAccumulateKArgsAndPassTo{4}{\composition}}%
{\endcomposition}%
\makeatother
\newcommand{\twinkle}{{Folk Song}{}{Twinkle Twinkle Little Star}}
\newcommand{\studentname}{{Student Name}}
\begin{document}
\begin{composition}{Folk Song}{}{Twinkle Twinkle Little Star}{Student Name}%
environment body
\end{composition}
\begin{mycomposition} \twinkle\studentname
environment body
\end{mycomposition}
\begin{mycomposition} \twinkle {Student Name}
environment body
\end{mycomposition}
\begin{mycomposition} {Folk Song}{}{Twinkle Twinkle Little Star} \studentname
environment body
\end{mycomposition}
\begin{mycomposition}{Folk Song}{}{Twinkle Twinkle Little Star}{Student Name}
environment body
\end{mycomposition}
\end{document}
composition
environment?composition
environment is irrelevant. I've added a second example, along with a bit more info that I discovered while making it; hopefully it helps to clarify the issue.composition
environment is not irrelevant in the sense that information is needed on what arguments it processes and on how it processes them.