Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

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.