# Retain side-effects but discard command output

The following code works, although I have a feeling my \settowidth method of discarding the output is not how it should be done:

\documentclass{article}
\newlength{\trashlength}
\long\def\ignoreoutput#1{%
\settowidth{\trashlength}{#1}%
}
\long\def\command#1{
This \gdef\stuff{Stored: #1} shouldn't be here.
}
%% Should not raise Missing \begin{document} error here:
%\ignoreoutput{\command}
\begin{document}
% Should produce "nothing":
no\ignoreoutput{\command{Side %\par %%%%% this breaks everything.
effect!}}thing.

% Should output the text previously stored:
\ifx\stuff\undefined No side effect.
\else \stuff \fi
\end{document}

When uncommenting the \par though, it breaks: with Paragraph ended before \@settodim was complete.

So how do I ignore commands that allow long input?

-

\newsavebox{\trashbox}
\long\def\ignoreoutput#1{\setbox\trashbox\vbox{\everypar{}\globaldefs1 #1}}


seems to work.

(Edit: make assignments global as per TH's answer, and locally disable LaTeX's \everypar-based mechanism for complaining about a missing \begin{document}.)

-
Ah, very short. Must have missed it when looking up \savebox etc... But it doesn't work before \begin{document} though (but I could defer it using AtBeginDocument) –  pascal Jan 15 '11 at 3:17
@pascal: That can be fixed. See my edits above. I think it would be safe to forgo the usage of \newsavebox and just use \setbox0 as in TH's answer, even without the extra group that he uses – since box registers with numbers below 10 are reserved for temporary use. –  Harald Hanche-Olsen Jan 15 '11 at 10:10
Perfect. I used \long\def\ignoreoutput#1{\setbox0\vbox{\everypar{}#1}} and it works. (since I use local macros in the ignored command, I prefer manual \gdef) –  pascal Jan 15 '11 at 18:03
Good call on the \everypar{}. –  TH. Jan 15 '11 at 21:00

I would use something similar to Harald's example (which appeared just before I posted this).

\long\def\executeglobally#1{
\begingroup
\setbox0\vbox{
\globaldefs1
#1%
}%
\endgroup
}

\def\foo{foo}
\executeglobally{asdf\def\foo{bar}asdf}
\foo
\bye


The \globaldefs1 makes assignments global.

-
thanks, didn't know about \globaldefs or temporary boxes. –  pascal Jan 15 '11 at 18:03

Just tried this, but it seems even fishier:

\documentclass{article}
\newlength{\trashlength}
\newsavebox{\trashbox}
\long\def\ignoreoutput#1{%
\sbox{\trashbox}{#1}%
\settowidth{\trashlength}{\usebox{\trashbox}}%
}
% etc like above

But it can break with Dimension too large.

-