Delayed evaluation (equivalent to := in Mathematica)?
In Sage, is there a way to define a function such that the expressions used are evaluated only when the function is called with specific values replacing its arguments? (In Mathematica, this is done by defining f(x_) : = some function(x).)
As an example, here is some otherwise useless code which is intended to give back a plot of x^r for arbitrary integer r.
myplot(r) = lambda r: plot(x^r,(x,-1,1))
Executing this line causes the errors copied below, which are identical to those produced if I simply execute plot(x^r,(x,-1,1))
by itself. So my interpretation is that Sage is immediately trying to evaluate the RHS of the function I'm defining. In Mathematica, this evaluation can be delayed using the ":=" syntax, so that if I then call "my plot(3)" it would go and evaluate plot(x^3,(x,-1,1))
which of course would produce the desired result. So, again, my question is whether there is something analogous in Sage?
(And yes, I have heard that Sage is short for "Sage is not Mathematica". But it's so great! Sage I mean.)
Thanks!
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/ext/fast_callable.pyx in sage.ext.fast_callable.ExpressionTreeBuilder.var (build/cythonized/sage/ext/fast_callable.c:6657)()
688 try:
--> 689 ind = self._vars.index(var_name)
690 except ValueError:
ValueError: 'x' is not in list
During handling of the above exception, another exception occurred:
ValueError Traceback (most recent call last)
/var/folders/mt/4xjm_x515mxdjkm49zmplt240000gq/T/ipykernel_91376/380259859.py in <module>
----> 1 __tmp__=var("r"); myplot = symbolic_expression(lambda r: plot(x**r,(x,-Integer(1),Integer(1)))).function(r)
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/calculus/all.py in symbolic_expression(x)
223 for param in s.parameters.values()):
224 vars = [SR.var(name) for name in s.parameters.keys()]
--> 225 result = x(*vars)
226 if isinstance(result, (tuple, list)):
227 return vector(SR, result).function(*vars)
/var/folders/mt/4xjm_x515mxdjkm49zmplt240000gq/T/ipykernel_91376/380259859.py in <lambda>(r)
----> 1 __tmp__=var("r"); myplot = symbolic_expression(lambda r: plot(x**r,(x,-Integer(1),Integer(1)))).function(r)
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/misc/decorators.py in wrapper(*args, **kwds)
489 options['__original_opts'] = kwds
490 options.update(kwds)
--> 491 return func(*args, **options)
492
493 #Add the options specified by @options to the signature of the wrapped
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/plot/plot.py in plot(funcs, *args, **kwds)
1981
1982 if hasattr(funcs, 'plot'):
-> 1983 G = funcs.plot(*args, **original_opts)
1984
1985 # If we have extra keywords already set, then update them
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/symbolic/expression.pyx in sage.symbolic.expression.Expression.plot (build/cythonized/sage/symbolic/expression.cpp:94285)()
12857 param = A[0]
12858 try:
> 12859 f = self._plot_fast_callable(param)
12860 except NotImplementedError:
12861 return self.function(param)
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/symbolic/expression.pyx in sage.symbolic.expression.Expression._plot_fast_callable (build/cythonized/sage/symbolic/expression.cpp:94693)()
12892 from sage.ext.fast_callable import fast_callable
12893 from sage.rings.complex_double import CDF
> 12894 return fast_callable(self, vars=vars, expect_one_var=True, domain=CDF)
12895
12896 ############
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/ext/fast_callable.pyx in sage.ext.fast_callable.fast_callable (build/cythonized/sage/ext/fast_callable.c:4638)()
463
464 etb = ExpressionTreeBuilder(vars=vars, domain=domain)
--> 465 et = x._fast_callable_(etb)
466
467 if isinstance(domain, sage.rings.abc.RealField):
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/symbolic/expression.pyx in sage.symbolic.expression.Expression._fast_callable_ (build/cythonized/sage/symbolic/expression.cpp:93534)()
12719 """
12720 from sage.symbolic.expression_conversions import fast_callable
> 12721 return fast_callable(self, etb)
12722
12723 def show(self):
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/symbolic/expression_conversions.py in fast_callable(ex, etb)
1866
1867 """
-> 1868 return FastCallableConverter(ex, etb)()
1869
1870 class RingConverter(Converter):
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/symbolic/expression_conversions.py in __call__(self, ex)
204 div = self.get_fake_div(ex)
205 return self.arithmetic(div, div.operator())
--> 206 return self.arithmetic(ex, operator)
207 elif operator in relation_operators:
208 return self.relation(ex, operator)
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/symbolic/expression_conversions.py in arithmetic(self, ex, operator)
1794 elif operator == mul_vararg:
1795 operator = _operator.mul
-> 1796 return reduce(lambda x,y: self.etb.call(operator, x,y), operands)
1797
1798 def symbol(self, ex):
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/symbolic/expression_conversions.py in <lambda>(x, y)
1794 elif operator == mul_vararg:
1795 operator = _operator.mul
-> 1796 return reduce(lambda x,y: self.etb.call(operator, x,y), operands)
1797
1798 def symbol(self, ex):
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/ext/fast_callable.pyx in sage.ext.fast_callable.ExpressionTreeBuilder.call (build/cythonized/sage/ext/fast_callable.c:7094)()
741 if fn is operator.pow:
742 base, exponent = args
--> 743 return self(base)**exponent
744 else:
745 return ExpressionCall(self, fn, [self(a) for a in args])
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/ext/fast_callable.pyx in sage.ext.fast_callable.ExpressionTreeBuilder.__call__ (build/cythonized/sage/ext/fast_callable.c:6236)()
617 return self.constant(x)
618
--> 619 return fc(self)
620
621 def _clean_var(self, v):
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/symbolic/expression.pyx in sage.symbolic.expression.Expression._fast_callable_ (build/cythonized/sage/symbolic/expression.cpp:93534)()
12719 """
12720 from sage.symbolic.expression_conversions import fast_callable
> 12721 return fast_callable(self, etb)
12722
12723 def show(self):
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/symbolic/expression_conversions.py in fast_callable(ex, etb)
1866
1867 """
-> 1868 return FastCallableConverter(ex, etb)()
1869
1870 class RingConverter(Converter):
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/symbolic/expression_conversions.py in __call__(self, ex)
198 operator = ex.operator()
199 if operator is None:
--> 200 return self.symbol(ex)
201
202 if operator in arithmetic_operators:
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/symbolic/expression_conversions.py in symbol(self, ex)
1815 ValueError: Variable 'z' not found...
1816 """
-> 1817 return self.etb.var(SR(ex))
1818
1819 def composition(self, ex, function):
/private/var/tmp/sage-9.6-current/local/var/lib/sage/venv-python3.10.3/lib/python3.10/site-packages/sage/ext/fast_callable.pyx in sage.ext.fast_callable.ExpressionTreeBuilder.var (build/cythonized/sage/ext/fast_callable.c:6736)()
689 ind = self._vars.index(var_name)
690 except ValueError:
--> 691 raise ValueError(f"Variable '{var_name}' not found in {self._vars}")
692 return ExpressionVariable(self, ind)
693
ValueError: Variable 'x' not found in ['r']
Just use normal python syntax