2

In continuation of the post, I try to make the following (simplified) code to work.

  • \timedelta uses 2 arguments.
  • Using a \gdef as the first argument is Ok.
  • Using a \gdef as the second argument is Nok.

I cannot go away from the exception

21: Paragraph ended before \timedelta@i was complete. []

\documentclass{article}

\makeatletter
\newcommand{\timedelta}[2]{\romannumeral0\timedelta@i#1:#2:}%
\def\timedelta@i #1:#2:#3:#4:%
   {\expandafter\timedelta@ii\the\numexpr#3*60+#4-#1*60-#2.}%
\def\timedelta@ii#1{\expandafter\timedelta@iii\the\numexpr
                    \if-#11440\fi #1}%
\def\timedelta@iii#1.{\expandafter\timedelta@iv\the\numexpr
                    (#1 + 30)/60 -1.#1.}%
\def\timedelta@iv #1.#2.{\expandafter\timedelta@v\the\numexpr
                    100+#2-60*#1\expandafter.\the\numexpr100+#1.}
\def\timedelta@v 1#1.1#2.{ #2:#1}
\makeatother

\begin{document}


\gdef\routeStart{01:27}
\expandafter\timedelta\expandafter{\routeStart}{01:27}% ok

\gdef\routeStop{01:27}
\expandafter\timedelta{16:03}\expandafter{\routeStop}% nok -> Paragraph ended before \timedelta@i was complete.

\end{document}

My Edits after the first answers

How to "expand" the two arguments? Thx!

\timedelta{\routeStart}{\routeStop}
  • \expandafter\timedelta{ applies expandafter to a { but that is not an expandable token – David Carlisle Nov 8 '17 at 18:35
  • Note that you don't use the \gdef as argument, but a macro (here \routeStart or \routeStop). – Skillmon Nov 8 '17 at 19:24
  • sorry for not having made the initial \timedelta expand automatically its two arguments. I have now added this to this initial answer of your post. As per the question here, my answer defines \timedeltaOO and \timedeltaXX which both would work with {\routeStart}{\routeStop} arguments. But simpler to use the enhanced \timedelta now there – user4686 Nov 8 '17 at 22:14
  • The second version perfectly fits my needs. Thks for the "ready to use" solution. Now, I have to study it ... – Joseph Marie Nov 9 '17 at 4:15
2

This could help:

\documentclass{article}

\makeatletter
\newcommand{\timedelta}[2]{\romannumeral0\timedelta@i#1:#2:}%
\def\timedelta@i #1:#2:#3:#4:%
   {\expandafter\timedelta@ii\the\numexpr#3*60+#4-#1*60-#2.}%
\def\timedelta@ii#1{\expandafter\timedelta@iii\the\numexpr
                    \if-#11440\fi #1}%
\def\timedelta@iii#1.{\expandafter\timedelta@iv\the\numexpr
                    (#1 + 30)/60 -1.#1.}%
\def\timedelta@iv #1.#2.{\expandafter\timedelta@v\the\numexpr
                    100+#2-60*#1\expandafter.\the\numexpr100+#1.}
\def\timedelta@v 1#1.1#2.{ #2:#1}
\makeatother

\newcommand\timeatled[2]{\timedelta{#2}{#1}}

\newcommand\timedeltaON[2]{\expandafter\timedelta\expandafter{#1}{#2}}
\newcommand\timedeltaNO[2]{\expandafter\timeatled\expandafter{#2}{#1}}
\newcommand\timedeltaOO[2]{\expandafter\timedeltaNO\expandafter{#1}{#2}}

\newcommand\timedeltaXN[2]
    {\expandafter\timedelta\expandafter{\romannumeral-`0#1}{#2}}
\newcommand\timedeltaNX[2]
    {\expandafter\timeatled\expandafter{\romannumeral-`0#2}{#1}}
\newcommand\timedeltaXX[2]
    {\expandafter\timedeltaNX\expandafter{\romannumeral-`0#1}{#2}}


\begin{document}


\gdef\routeStart{01:27}
\timedeltaON{\routeStart}{01:27}% ok

\timedeltaOO{\routeStart}{01:27}% ok

\timedeltaXX{\routeStart}{01:27}% ok

\gdef\routeStop{01:27}

\timedeltaNO{16:03}{\routeStop}% ok

\timedeltaOO{16:03}{\routeStop}% ok

\timedeltaXX{16:03}{\routeStop}% ok

\end{document}

enter image description here

LaTeX3 has a "generate variant" all purpose facility which solves these problems once and for all...

Notice that \timedeltaXX can be nested with itself (i.e. serve as either first or second argument of itself).

  • original \timedelta should have expanded its arguments but I was too lazy... (i.e. what is called \timedeltaXX here should have been the original \timedelta). – user4686 Nov 8 '17 at 18:57
  • O stands for "open = expand once" and N for "nothing special, take argument as is", and X for "force expansion of first token until non further expandable" (this is in itself expandable operation, contrarily to putting the argument in an \edef, which would break expandability of \timedelta macro) – user4686 Nov 8 '17 at 19:03
  • +1 for the \romannumeral trick (never would have thought of it, to be honest) – Skillmon Nov 8 '17 at 19:15
  • @Skillmon it is part of each TeXpandabler's bag of tricks and passes from generation to generation... – user4686 Nov 8 '17 at 19:45
1

You misuse \expandafter. A way how you could expand the second argument of the macro would be, to define a second macro, which contains the macro and its first argument and then use \expandafters to expand an argument prior to execute that second macro:

\documentclass{article}

\makeatletter
\newcommand{\timedelta}[2]{\romannumeral0\timedelta@i#1:#2:}%
\def\timedelta@i #1:#2:#3:#4:%
   {\expandafter\timedelta@ii\the\numexpr#3*60+#4-#1*60-#2.}%
\def\timedelta@ii#1{\expandafter\timedelta@iii\the\numexpr
                    \if-#11440\fi #1}%
\def\timedelta@iii#1.{\expandafter\timedelta@iv\the\numexpr
                    (#1 + 30)/60 -1.#1.}%
\def\timedelta@iv #1.#2.{\expandafter\timedelta@v\the\numexpr
                    100+#2-60*#1\expandafter.\the\numexpr100+#1.}
\def\timedelta@v 1#1.1#2.{ #2:#1}
\makeatother

\begin{document}


\gdef\routeStart{01:27}
\expandafter\timedelta\expandafter{\routeStart}{01:27}% ok

\gdef\routeStop{01:27}
\def\tempmacro{\timedelta{16:03}}%
\expandafter\tempmacro\expandafter{\routeStop}%
%\expandafter\timedelta{16:03}\expandafter{\routeStop}% nok -> Paragraph ended before \timedelta@i was complete.

\end{document}

What \expandafter does is (unprecisely described) it expands the second token prior to the first one (if it's expandable). In your example, every character of the first argument is a token, the correct way would be therefore jumping over each of those characters using an \expandafter, so the correct way to use \expandafter in that case would be:

\expandafter\timedelta\expandafter{\expandafter1\expandafter6\expandafter:\expandafter0\expandafter3\expandafter}\expandafter{\routeStop}%

Which is really cumbersome...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.