# Revision history [back]

I think the confusion here is between the fact that your examples use f(1) as an expression, but Python functions and the values those functions take are two different things. There are several ways to get around this:

# method 1
def f(n):
if n == 0:
retfunc(x) = 1
else:
retfunc(x) = add(x*f(n-k) for k in (1..n))
return retfunc

sage: f(0)
x |--> 1
sage: f(1)
x |--> x
sage: f(2)
x |--> x^2 + x
sage: f(3)
x |--> (x^2 + x)*x + x^2 + x
sage: f(3)(4)
100


(2) Use expressions instead, and substitute manually:

# method 2
def f(n):
if n == 0:
retexpr = 1
else:
retexpr = add(x*f(n-k) for k in (1..n))
return retexpr

sage: f(0)
1
sage: f(1)
x
sage: f(2)
x^2 + x
sage: f(3)
(x^2 + x)*x + x^2 + x
sage: f(3)(x=4)
100


(3) Evaluate the function at x before doing the addition in your code:

# method 3
def f(n) :
def retfunc(x) :
return 1 if n == 0 else x*add(f(n-k)(x) for k in (1..n))
return retfunc

sage: [f(i) for i in [0..3]]
[<function retfunc at 0x10eee66e0>, <function retfunc at 0x10eee6668>, <function retfunc at 0x10eee6758>, <function retfunc at 0x10eee67d0>]
sage: [f(i)(x) for i in [0..3]]
[1, x, (x + 1)*x, ((x + 1)*x + x + 1)*x]
sage: [f(i)(x) for i in [0..3]]
[1, x, (x + 1)*x, ((x + 1)*x + x + 1)*x]
sage: f(3)(x=4)
100


I'd prefer (1) or (2) because it's somewhat easier to work with Sage-level objects in a calculus-y way than Python functions, but YMMV.

I think the confusion here is between the fact that your examples use f(1) as an expression, but Python functions and the values those functions take are two different things. There are several ways to get around this:

# method 1
def f(n):
if n == 0:
retfunc(x) = 1
else:
retfunc(x) = add(x*f(n-k) for k in (1..n))
return retfunc

sage: f(0)
x |--> 1
sage: f(1)
x |--> x
sage: f(2)
x |--> x^2 + x
sage: f(3)
x |--> (x^2 + x)*x + x^2 + x
sage: f(3)(4)
100


(2) Use expressions instead, and substitute manually:manually when you want to call it later:

# method 2
def f(n):
if n == 0:
retexpr = 1
else:
retexpr = add(x*f(n-k) for k in (1..n))
return retexpr

sage: f(0)
1
sage: f(1)
x
sage: f(2)
x^2 + x
sage: f(3)
(x^2 + x)*x + x^2 + x
sage: f(3)(x=4)
100


(3) Evaluate the function at x before doing the addition in your code:

# method 3
def f(n) :
def retfunc(x) :
return 1 if n == 0 else x*add(f(n-k)(x) for k in (1..n))
return retfunc

sage: [f(i) for i in [0..3]]
[<function retfunc at 0x10eee66e0>, <function retfunc at 0x10eee6668>, <function retfunc at 0x10eee6758>, <function retfunc at 0x10eee67d0>]
sage: [f(i)(x) for i in [0..3]]
[1, x, (x + 1)*x, ((x + 1)*x + x + 1)*x]
sage: [f(i)(x) for i in [0..3]]
[1, x, (x + 1)*x, ((x + 1)*x + x + 1)*x]
sage: f(3)(x=4)
100


I'd prefer (1) or (2) because it's somewhat easier to work with Sage-level objects in a calculus-y way than Python functions, but YMMV.

I think the confusion here is between involves the fact that your examples use f(1) as an expression, but Python functions and the values those functions take are two different things. There are several ways to get around this:

# method 1
def f(n):
if n == 0:
retfunc(x) = 1
else:
retfunc(x) = add(x*f(n-k) for k in (1..n))
return retfunc

sage: f(0)
x |--> 1
sage: f(1)
x |--> x
sage: f(2)
x |--> x^2 + x
sage: f(3)
x |--> (x^2 + x)*x + x^2 + x
sage: f(3)(4)
100


(2) Use expressions instead, and substitute manually when you want to call it later:

# method 2
def f(n):
if n == 0:
retexpr = 1
else:
retexpr = add(x*f(n-k) for k in (1..n))
return retexpr

sage: f(0)
1
sage: f(1)
x
sage: f(2)
x^2 + x
sage: f(3)
(x^2 + x)*x + x^2 + x
sage: f(3)(x=4)
100


(3) Evaluate the function at x before doing the addition in your code:

# method 3
def f(n) :
def retfunc(x) :
return 1 if n == 0 else x*add(f(n-k)(x) for k in (1..n))
return retfunc

sage: [f(i) for i in [0..3]]
[<function retfunc at 0x10eee66e0>, <function retfunc at 0x10eee6668>, <function retfunc at 0x10eee6758>, <function retfunc at 0x10eee67d0>]
sage: [f(i)(x) for i in [0..3]]
[1, x, (x + 1)*x, ((x + 1)*x + x + 1)*x]
sage: [f(i)(x) for i in [0..3]]
[1, x, (x + 1)*x, ((x + 1)*x + x + 1)*x]
sage: f(3)(x=4)
100


I'd prefer (1) or (2) because it's somewhat easier to work with Sage-level objects in a calculus-y way than Python functions, but YMMV.