# How to pass parameters to Sage from Sagetex?

I haven't found a way to pass parameters to a sagesilent environment, so I wonder if it's possible. My final purpose is to combine sagetex with probsoln. The package probsoln lets you manage a problem database, and this problems can take optional arguments. So when I call one of these problems, I want to pass its parameters right to sagetex to make the calculations.

I have prepared a MWE which is probsoln independent. It builds a polynom in sagetex, and what I would like is to change the definition of np=15 (inside sagesilent) for np=\np

If only I could manage how to expand every LaTeX macro inside sagesilent, this could be easily done. Actually, I think that this question could be formulated also independently of sage and sagetex, something like this: How to replace the macros inside an environment for its definition/value before processing the environment?

Any ideas?

The MWE:

\documentclass{article}%
\PassOptionsToPackage{T1}{fontenc}
\usepackage{fontenc}
\usepackage[utf8]{inputenc}

\usepackage{sagetex}
\pagestyle{empty}

\begin{document}
\def\np{15}

\begin{sagesilent}
np=15 #grado del polinomio p
p1=0
pcoeffs=range(np+1)
x = var('x')
for i in range(np+1):
pcoeffs[i]= Integer(randint(-8,8))
p1=p1+pcoeffs[i]*x^i
\end{sagesilent}
\noindent This is a polynom of grade $\np$:

$\sage{p1}$

\end{document}


Expanding macros inside a sagesilent requires changing the catcode treatment within the environment. The code below will create a sagesilentexp environment in which macros are expanded.

Macros will behave a little differently than normal. A macro that doesn't take arguments won't eat trailing spaces, because the spaces are now literal. If a macro that doesn't take arguments is followed by {}, then the {} will appear in the code as literal {}. I've improved the answer in light of this question, so that braces following a macro that doesn't take an argument will vanish as expected. If you need a literal backslash, you can use \textbackslash (this required a redefinition). I've also redefined \\ to give a literal backslash, since its normal LaTeX use is redundant in this context and \\ is more compact than \textbackslash. Similarly, \{ and \} may be used to add literal braces.

\makeatletter
\newenvironment{sagesilentexp}%
{\ST@beginsfbl%
% All changes are in \verbatim@processline
\def\verbatim@processline{%
\begingroup
% Redefine escapes so they write to file in literal fashion
\edef\{{\@charlb}%
\edef\}{\@charrb}%
\edef\\{\@backslashchar}
\let\textbackslash\@backslashchar
% Retokenize with new catcodes
\everyeof{\noexpand}%
\endlinechar-1\relax
\let\do\@makeother\dospecials%
\catcode\\=0%
\catcode\{=1%
\catcode\}=2%
\xdef\verbatim@line@retok{\expandafter\scantokens\expandafter{\the\verbatim@line}}%
\endgroup
% Strip out any brace groups, and warn of unexpandable macros
\let\verbatim@line@retok@final\empty
\let\verbatim@line@retok@last\verbatim@line@retok
\expandafter\gobble@retok@braces\verbatim@line@retok\@nil
\expandafter\check@retok@unexpandable\verbatim@line@retok@final\@nil
% Write retokenized result
% Leading space is important since Python is whitespace-sensitive
\ST@wsf{ \verbatim@line@retok@final}%
}%
\verbatim@start}%
{\ST@endsfbl\@esphack}
\def\gobble@retok@braces#1#2\@nil{%
\if\relax\detokenize{#2}\relax
\ifx\verbatim@line@retok@last\verbatim@line@retok@final
\else
\let\verbatim@line@retok@last\verbatim@line@retok@final
\let\verbatim@line@retok@final\empty
\expandafter\gobble@retok@braces\verbatim@line@retok@last\@nil
\fi
\else
\gobble@retok@braces#2\@nil
\fi}
\def\check@retok@unexpandable#1#2\@nil{%
\ifcat#1\relax
\PackageWarning{}{Verbatim text contained unexpandable macro \string#1}%
\else
\if\relax\detokenize{#2}\relax
\else
\check@retok@unexpandable#2\@nil
\fi
\fi}
\makeatother

• Great answer! Thanks for the effort. In the meanwhile, for my current project, I've switched my workflow according my own (previous) answer. However, and nodoubt, I'll take your solution into account for future documents. – Pablo B. Jan 14 '15 at 10:20

I'm posting an answer to my own question because I've found a way to deal with this thing. So if anyone is trying to do something similar, here is my solution.

The dependence on sageto generate my random problems is so heavy than instead of using probsoln to manage the problem database, I've found easier to let sage write both the problem text and the solution.

The workflow would start by creating a .tex file with just a sagesilent environment, where every problem is defined as a sage function, with his own parameters. This file is inserted with \input after \begin{document} in the main tex file.

After that, when you need to use one of them, you just have to call the function inside a sagesilentin the main document.

What makes the trick is that these problem-functions return two parameters, one called problem and one called solution, which are LaTeX strings and can be called along the main document just with \sagestr{problem} or \sagestr{solution}

If anyone thinks a way to improve this workflow, please comment.

• This is the kind of thing I would do. I often find that it's easiest to push as much of the work as possible into Sage, which (for me, at least...) is a much nicer programming environment than TeX. Write functions, build up TeX strings in Sage, and then pull them into your document with \sagestr`. That's my usual strategy. – Dan Drake Apr 21 '15 at 16:03
• A nice trick: if you have a lot of Sage/Python code, put it all in a .py file, and then in a sagesilent environment, do "from foo.py import *" and you get access to all your functions. (It does have to be a .py file, so it has to use proper Python syntax -- none of Sage's syntactic sugar.) – Dan Drake Apr 21 '15 at 16:06