2

I have this MWE that tries to return a value from \l_example_foo_int from a function:

\documentclass[a4paper]{article}

\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\returnvalue}{}{
  \int_new:N \l_example_foo_int
  \int_add:Nn \l_example_foo_int {10}
  % return value
  \l_example_foo_int
}

\begin{document}

Should print value here:
\returnvalue

\int_new:N \l_example_bar_int
\int_add:Nn \l_example_bar_int \returnvalue

Should print value here:
\l_example_bar_int

\end{document}

It throws an error however.

Wondering how to get it so it can return a value from a function and that value can be typeset or \typeout or the like.

Lance
  • 1,799
  • Again you have a ...new instruction inside of NewDocumentCommand.. for your real issue: \int_use:N \foo_int could help.. but using int_add will make the whole thing unexpandable –  Mar 26 '18 at 17:46
  • If I move \int_new outside of the function I still get an error ! Missing number, treated as zero.. – Lance Mar 26 '18 at 17:48
  • The \int_new is not the cause of your problem. . ... and I am typing on my smartphone therefore no answer –  Mar 26 '18 at 17:50
  • Seeing now the real problem (being at my computer at home: \returnvalue is unexpandable and can't be fed to \int_add:Nn again –  Mar 26 '18 at 18:04
  • I don't have any experience yet with "expansion" stuff, so I'm not quite sure what you mean, or how you knew that. – Lance Mar 26 '18 at 18:06
  • On expansion, see for example https://tex.stackexchange.com/questions/248741/what-does-expanding-mean-in-latex, https://tex.stackexchange.com/questions/35039/why-isnt-everything-expandable, https://tex.stackexchange.com/questions/66118/advantages-and-disadvantages-of-fully-expandable-macros – Joseph Wright Mar 26 '18 at 19:41
  • 1
    You might also be interested in https://tex.stackexchange.com/q/56294/86 – Andrew Stacey Mar 26 '18 at 21:06

2 Answers2

3

\int_add:Nn is not expandable (it has no red star in the documentation). So it won't work like this. But you can use \int_eval:Nn:

\documentclass[a4paper]{article}

\usepackage{xparse}

\begin{document}

\ExplSyntaxOn
\int_new:N \l_example_foo_int
\int_new:N  \l_example_bar_int

\NewDocumentCommand\returnvalue {} {
 \int_eval:n { \l_example_foo_int + 10}
}

\returnvalue\par

\int_add:Nn \l_example_bar_int {\returnvalue}

\int_use:N \l_example_bar_int

\ExplSyntaxOff
\end{document} 
Ulrike Fischer
  • 327,261
  • Would be helpful to know (1) why you moved \int_new:N out of the function, (2) why the need for \int_use:N (I read in the documentation that it "recovers the content and places it in the input stream" but I don't know what that means or where it was before the input stream, and (3) if \int_eval:n is good-practice (since eval is avoided in some programming languages). – Lance Mar 26 '18 at 18:10
  • \int_new:N isn't expandable either. If you want a command that can be used in a calculation it shouldn't contain this stuff. – Ulrike Fischer Mar 26 '18 at 18:47
3

\int_add:Nn is not expandable, i.e. it will not be fed correctly to \int_add:Nn again.

I suggest to use two separate commands, one that adds a value and another one, that is a wrapper for \l_example_foo_int.

However, the real use case is unclear, so the whole wrapping in \returnvalue is not really necessary, most likely.

Don't use a \...new:N call inside of a document level macro unless really checking. The next call of the original \returnvalue would try to define \int_new:N ... again, which is an error.

\documentclass[a4paper]{article}

\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn

\int_new:N \l_example_foo_int
\int_new:N \l_example_bar_int

\NewDocumentCommand{\addvalue}{}{
  \int_add:Nn \l_example_foo_int {10}
}

\NewDocumentCommand{\returnvalue}{}{
  \int_use:N \l_example_foo_int
}

\begin{document}

Should print value here:
\addvalue
\returnvalue


\int_add:Nn \l_example_bar_int {\returnvalue}

Should print value here:
\int_use:N \l_example_bar_int

\end{document}
  • So this means all variables need to be declared globally then is what im understanding – Lance Mar 26 '18 at 18:13
  • @LancePollard: In most cases, yes. If you want to have them local, use \int_set:N etc. in a group –  Mar 26 '18 at 18:14
  • I was hoping to have the function behave like in a normal programming language where you do (a better name instead of returnvalue would be initializeint lets say for this example) initializeint and the output is the result of the function. I would like for it to work like that if at all possible. – Lance Mar 26 '18 at 18:15
  • @LancePollard: You fell into a 'normal' programmer trap however. That's what I had to learn some years ago as well: TeX etc. is different. As soon as you perform an assignment the whole thing is unexpandable... –  Mar 26 '18 at 18:17
  • Ok, need to learn more about expansion then. Thank you. – Lance Mar 26 '18 at 18:18
  • Sidenote about global variable declaration. How then do you dynamically generate a variable name at runtime, just use int_set or tl_set, etc. I'm assuming, no \int_new or \tl_new – Lance Mar 26 '18 at 18:22
  • @LancePollard: \int_if_exist:cTF {l_my_#1_ int} {\int_new:c {\l_my_#1_int}{% false branch, if needed} where #1 is a macro argument, for example –  Mar 26 '18 at 18:24
  • 1
    @ChristianHupfer \int_new:N creates always a global variable. – Ulrike Fischer Mar 26 '18 at 18:53
  • @UlrikeFischer: I did not claiming something other, did I? I wrote that they should be declared globally in my cases, otherwise locally with the \...set:N etc. macros –  Mar 26 '18 at 18:55
  • @ChristianHupfer you wrote above "if you want to have them local, use \int_set:N etc. in a group" the etc sounded a bit misunderstable. – Ulrike Fischer Mar 26 '18 at 18:57
  • @LancePollard: That's unrelated to your main question, however –  Mar 26 '18 at 19:44