# Using matrix() inside a user function prevents argument evaluation

This function:

f(x) = x*matrix([[5]])


Will produce this result:

In: f(3)
Out: [5*x]


I would expect the result to be the same as this:

In: 3*matrix([[5]])
Out: [15]


What am I missing? How come the argument supplied ('x') isn't being evaluated inside the function?

Thank you

edit retag close merge delete

Sort by » oldest newest most voted

Hello, @chris233! I had the same problem some time ago. Check this related questions:

1. https://ask.sagemath.org/question/476... (my related question, with an excellent answer by @rburing, with a list of additional cases where this particular syntax for function definition fails.)
2. https://ask.sagemath.org/question/104... (this one has an excellent to-the-point explanation of this problem by @nbruin; this should answer your doubt.)

The only way around this problem (as far as I know) is to use pure Python syntax for function definition (In this case, "function" in the sense of computer pŕogramming, as a synonym of "subroutine", not "function" in the mathematical sense):

def f(x):
return x * matrix([[5]])


(In my humble opinion, this is very unfortunate because mathematical function definition, like the one you intended, is a very convenient feature.)

I hope this helps!

more

You can still create a symbolic function via the function function... :

f=function("f", eval_func=lambda self,*args:args[0]*matrix[[5]])


(or possibly

f=function("f", evalf_func=lambda self,*args:[u*matrix[[5]] for u in args])


depending of the semantics you wish to have for non-scalar arguments...)

The point is that f can now appear in symbolic expressions, where its argument is symbolic. This allows its use in other symbolic expressions. Contrast :

sage: fs=function("fs", evalf_func=lambda self, *args: len(divisors(args[0])))
sage: gs(x)=fs(x)^2
sage: gs
x |--> fs(x)^2
sage: fs
fs


where fs is treated as some "primitive" functoin, with :

sage: def fp(x): return len(divisors(x))
sage: gp(x)=fp(x)^2
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/usr/local/sage-9/local/lib/python3.9/site-packages/sage/arith/misc.py in divisors(n)
1484     try:
-> 1485         m = n.divisors
1486     except AttributeError:

/usr/local/sage-9/local/lib/python3.9/site-packages/sage/structure/element.pyx in sage.structure.element.Element.__getattr__ (build/cythonized/sage/structure/element.c:4708)()
492         """
--> 493         return self.getattr_from_category(name)
494

/usr/local/sage-9/local/lib/python3.9/site-packages/sage/structure/element.pyx in sage.structure.element.Element.getattr_from_category (build/cythonized/sage/structure/element.c:4820)()
505             cls = P._abstract_element_class
--> 506         return getattr_from_other_class(self, cls, name)
507

/usr/local/sage-9/local/lib/python3.9/site-packages/sage/cpython/getattr.pyx in sage.cpython.getattr.getattr_from_other_class (build/cythonized/sage/cpython/getattr.c:2618)()
371         dummy_error_message.name = name
--> 372         raise AttributeError(dummy_error_message)
373     attribute = <object>attr

AttributeError: 'sage.symbolic.expression.Expression' object has no attribute 'divisors'

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
<ipython-input-90-05136176d065> in <module>
----> 1 __tmp__=var("x"); gp = symbolic_expression(fp(x)**Integer(2)).function(x)

<ipython-input-87-c759a1d7e016> in fp(x)
----> 1 def fp(x): return len(divisors(x))

/usr/local/sage-9/local/lib/python3.9/site-packages/sage/arith/misc.py in divisors(n)
1492             one = parent(n)(1)
1493             output = [one]
-> 1494             for p, e in f:
1495                 prev = output[:]
1496                 pn = one

TypeError: 'sage.symbolic.expression.Expression' object is not iterable


where the expression serving as "function body" is somehow evaluated during the creation of the symbolic expression ; this entails trying to evaluate divisors(x), which fails, since divisors is not a symbolic function...

Note that fs has a, evalf_func method, but not an eval_func method : this ensures that fs(x) will remain unevaluated, whereas fs(12) will be (numerically) evaluated (and return 12). Type function? for more details (quite important here...).

HTH,

more