# Why my parameter is set to zero when command is called from inner brace?

I have this piece of code:

\documentclass{scrartcl}
\usepackage{pbox,calc}

\makeatletter
\newcommand*{\strippt}[1]{\strip@pt#1}
\makeatother

\newlength{\pointsExo}
\setlength{\pointsExo}{4pt}
\newlength{\pointsSousTotal}
\setlength{\pointsSousTotal}{0pt}

\newlength{\souspointsExo}
\newcommand{\sousPoints}[1]{
\setlength{\souspointsExo}{#1pt}
\setlength{\pointsSousTotal}{\pointsSousTotal + #1pt}
{\scriptsize{(#1~\ifdim#1pt=1pt point\else points\fi/\strippt\pointsExo)}}
}

\newcommand{\subexo}[2]{
\textsf{ %%If I comment these two lines, the sub-total is correct
#1\hfill\sousPoints{#2}% Points
}        %%If I comment these two lines, the sub-total is correct
\medskip
}

\newcommand{\exercice}[2]{
\setlength{\pointsExo}{#2pt}
\setlength{\pointsSousTotal}{0pt}
\medskip
#1\hfill#2 Points% Points
\medskip
}

\begin{document}
\exercice{A first one}{2.5}
\subexo{Anything}{2}

\subexo{Something}{0.5}

Sub-Total: \strippt\pointsSousTotal %should display 2.5

\exercice{A title}{4}
\subexo{another thing}{2.5}

\subexo{and a thing}{1.5}

Sub-Total: \strippt\pointsSousTotal %should display 4

\end{document}


The problem with this is that it should display something like this:

A first one 2.5 Points

Anything (2 points/2.5)

Something (0.5 points/2.5)

Sub-Total: 2.5

A title

another thing (2.5 points/4)

and a thing (1.5 points/4)

Sub-Total: 4

But, unless I comment the two indicated lines (currently, an enclosing \textsf{...}, but the problem is the same as soon as I enclose the \sousPoints{#2} between two curly braces), I get this:

A first one 2.5 Points

Anything (2 points/2.5)

Something (0.5 points/2.5)

Sub-Total: 0

A title

another thing (2.5 points/4)

and a thing (1.5 points/4)

Sub-Total: 0

What is wrong with using length inside an enclosing brace {...} ? Is it a bug ? A bad understanding of how commands work ?

-
your \setlength are local settings so the values are restored at the end of a group. (Also you are missing % from the ends of lots of lines.) – David Carlisle Apr 15 '14 at 23:16
@HarishKumar but if it's not grouped the OP had better use \normalfont or some such to restore things afterwards – David Carlisle Apr 15 '14 at 23:18
@DavidCarlisle You are right. :) – Harish Kumar Apr 15 '14 at 23:19
@DavidCarlisle Thanks, is there a way to workaround this ? Should I add % to all lines of a command ? Are there documentation or short tutorial about this ? – lauhub Apr 15 '14 at 23:19
On % see tex.stackexchange.com/questions/7453/… – David Carlisle Apr 15 '14 at 23:25

You need a global assignment for the effects to be seen outside the group:

\documentclass{scrartcl}
\usepackage{pbox,calc}

\makeatletter
\newcommand*{\strippt}[1]{\strip@pt#1}
\makeatother

\newlength{\pointsExo}
\setlength{\pointsExo}{4pt}
\newlength{\pointsSousTotal}
\setlength{\pointsSousTotal}{0pt}

\newlength{\souspointsExo}
\newcommand{\sousPoints}[1]{% don't let egreg get points for missing %
\setlength{\souspointsExo}{#1pt}% don't let egreg get points for missing %
\setlength{\pointsSousTotal}{\pointsSousTotal + #1pt}% don't let egreg get points for missing %
\global\souspointsExo=\souspointsExo % a bit costly of save stack but unlikely to have 1000s of these.
\global\pointsSousTotal=\pointsSousTotal
{\scriptsize{(#1~\ifdim#1pt=1pt point\else points\fi/\strippt\pointsExo)}}% don't let egreg get points for missing %
}

\newcommand{\subexo}[2]{% don't let egreg get points for missing %
\textsf{%%If I comment these two lines, the sub-total is correct
#1\hfill\sousPoints{#2}% Points
}%%If I comment these two lines, the sub-total is correct
\medskip
}

\newcommand{\exercice}[2]{% don't let egreg get points for missing %
\setlength{\pointsExo}{#2pt}% don't let egreg get points for missing %
\setlength{\pointsSousTotal}{0pt}% don't let egreg get points for missing %
\medskip
#1\hfill#2 Points% Points
\medskip
}

\begin{document}
\exercice{A first one}{2.5}
\subexo{Anything}{2}

\subexo{Something}{0.5}

Sub-Total: \strippt\pointsSousTotal %should display 2.5

\exercice{A title}{4}
\subexo{another thing}{2.5}

\subexo{and a thing}{1.5}

Sub-Total: \strippt\pointsSousTotal %should display 4

\end{document}

-
% don't let egreg get points for missing % brilliant :) – cmhughes Apr 15 '14 at 23:27
@cmhughes let's hope he doesn't notice – David Carlisle Apr 15 '14 at 23:28
I did. I'll upvote this nonetheless. – egreg Apr 15 '14 at 23:36

I post here is a supplemental test I made. I post it to demonstrate the effect of \setlength when it is inside or outside a group (a possible workaround to my problem that David Carlisle suggested in its first comment to my question).

However, I prefer David Carlisle 's answer with \global. It allows to display and set the value within one single command (since I will never a document with more than 50 calls to this command, so it will not consume so much resources).

\documentclass{scrartcl}
\usepackage{pbox,calc}

\makeatletter
\newcommand*{\strippt}[1]{\strip@pt#1}
\makeatother

\newlength{\pointsTotal}
\setlength{\pointsTotal}{0pt}

\newcounter{numExercice}
\newlength{\pointsExo}
\setlength{\pointsExo}{4pt}
\newlength{\pointsSousTotal}
\setlength{\pointsSousTotal}{0pt}

\newlength{\souspointsExo}
\newcommand{\sousPoints}[1]{% Will only display the points, not make the assignement
{\scriptsize{(#1~\ifdim#1pt<2pt point\else points\fi/\strippt\pointsExo)}}%
}

\newcounter{sousExercice}[numExercice]
\newcommand{\subexo}[2]{%
\stepcounter{sousExercice}%
\setlength{\souspointsExo}{#2pt}%makes the assignment outside of the group, no global required
\setlength{\pointsSousTotal}{\pointsSousTotal + #2pt}%makes the assignment outside of the group, no global required
\medskip
\textsf{%
\textbf{\arabic{numExercice}.\arabic{sousExercice}} :~#1%
\hfill\sousPoints{#2}% Points
}
}

\newcommand{\exercice}[2]{%
\stepcounter{numExercice}%
\setlength{\pointsExo}{#2pt}%
\setlength{\pointsSousTotal}{0pt}%
\setlength{\pointsTotal}{\pointsTotal + #2pt}%
\medskip

\textbf{Exercice \arabic{numExercice}} :~#1\hfill%
{\normalsize{(#2~\ifdim#2pt<2pt point\else points\fi)}}% Points

\medskip
}

\newcommand{\subtotal}{\strippt\pointsSousTotal}

\newcommand{\Total}{Total des points : \strippt\pointsTotal}

\begin{document}
\exercice{A first one}{2.5}
\subexo{Anything}{2}

\subexo{Something}{0.5}

Sub-Total: \strippt\pointsSousTotal

\exercice{A title}{4}
\subexo{another thing}{2.5}

\subexo{and a thing}{1.5}

Sub-Total: \strippt\pointsSousTotal

\end{document}

-