Ask Your Question

# Revision history [back]

### Is this a bug or intended behavior?

Hello, SageMath Community!

I was trying to define the function $\tau(n)=$ "number of divisors of $n$" in Sage, so I tried this:

tau(n) = len(divisors(n))


After pressing ENTER, I get the following traceback:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-7aac193e89de> in <module>()
----> 1 __tmp__=var("n"); tau = symbolic_expression(len(divisors(n))).function(n)

/Scientific/SageMath/local/lib/python2.7/site-packages/sage/arith/misc.pyc in divisors(n)
1494             one = parent(n)(1)
1495             output = [one]
-> 1496             for p, e in f:
1497                 prev = output[:]
1498                 pn = one

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


However, I can use exactly the same definition of the function by means of Python's standard function definition mechanism:

def tau(n):
return len(divisors(n))


I am not completely sure, but the following behaviour seems to be related. An alternative definition of $\tau$ would be:

tau(n) = sigma(n, 0)


However, this produces the following traceback:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-016584cdbd3f> in <module>()
----> 1 __tmp__=var("n"); tau = symbolic_expression(sigma(n,Integer(0))).function(n)

/Scientific/SageMath/local/lib/python2.7/site-packages/sage/arith/misc.pyc in __call__(self, n, k)
1595             130
1596         """
-> 1597         n = ZZ(n)
1598         k = ZZ(k)
1599         one = ZZ(1)

/Scientific/SageMath/local/lib/python2.7/site-packages/sage/structure/parent.pyx in sage.structure.parent.Parent.__call__ (build/cythonized/sage/structure/parent.c:9197)()
898         if mor is not None:
899             if no_extra_args:
--> 900                 return mor._call_(x)
901             else:
902                 return mor._call_with_args(x, args, kwds)

/Scientific/SageMath/local/lib/python2.7/site-packages/sage/structure/coerce_maps.pyx in sage.structure.coerce_maps.NamedConvertMap._call_ (build/cythonized/sage/structure/coerce_maps.c:5942)()
286             raise TypeError("Cannot coerce {} to {}".format(x, C))
287         cdef Map m
--> 288         cdef Element e = method(C)
289         if e is None:
290             raise RuntimeError("BUG in coercion model: {} method of {} returned None".format(self.method_name, type(x)))

/Scientific/SageMath/local/lib/python2.7/site-packages/sage/symbolic/expression.pyx in sage.symbolic.expression.Expression._integer_ (build/cythonized/sage/symbolic/expression.cpp:8690)()
1085             n = self.pyobject()
1086         except TypeError:
-> 1087             raise TypeError("unable to convert %r to an integer" % self)
1088         if isinstance(n, sage.rings.integer.Integer):
1089             return n

TypeError: unable to convert n to an integer


However, I can do:

def tau(n):
return sigma(n, 0)


Of course, it is possible to evaluate the formulas len(divisors(n)) and sigma(n, 0), when $n$ has a particular value---n=50, for example.

OS: Ubuntu 18.04.2 LTS

SageMath version: 8.8, dated 2019-06-26

Python version: 2.7.15

Possible explanation: SageMath seems to be trying to evaluate part of the body of the function during compile-time, instead of defering it to execution-time, as Python does.