# Define function over symbolic ring

I want to define a function over a dynamic number of variables, but find no way to coerce list, tuple or string to symbolic ring. Is there some Python / pre-parse / magic which can make this work? A failed example follows

sage: var( 'x1 x2 x3' )
sage: function('xxx')(x1,x2)    # A function of a fixed, pre-programmed number of variables
xxx(x1, x2)
sage: n = 3
sage: ' '.join('x'+str(i+1) for i in range(n))    # A string
'x1 x2 x3'
sage: eval( ' '.join('x'+str(i+1)+',' for i in range(n)) )    # A tuple
(x1, x2, x3)
sage: function('yyy')( eval( ' '.join('x'+str(i+1)+',' for i in range(n)) ) )
Traceback (most recent call last):
...
TypeError: cannot coerce arguments: no canonical coercion from <type 'tuple'> to Symbolic Ring

edit retag close merge delete

Sort by » oldest newest most voted

There's a python trick to unpack an iterable into an argument list in a function call:

sage: function('f')(*(SR.symbol("x%s"%i) for i in range(n)))
f(x0, x1, x2)

more

Thanks. This solves the immediate problem.

( 2017-05-06 20:36:57 +0100 )edit

I cannot imagine the reason for doing this, but if the dynamic number of variables is somehow bounded in the application, then an adaptation of the following may work (in a way that i do not really like, since generally explicit is better than implicit...)

sage: def vars(n):    return eval( "','.join( 'x%%s'%%j for j in range(1,%s) )" % (n+1) )
sage: var( vars(9) )
(x1, x2, x3, x4, x5, x6, x7, x8, x9)
sage: eval( "function('yyy')( %s )" % vars(9) )
yyy(x1, x2, x3, x4, x5, x6, x7, x8, x9)
sage: eval( "function('yyy')( %s )" % vars(4) )
yyy(x1, x2, x3, x4)


(For an explicit special meaningful situation, i would rethink, and very probably go on a different path...)

more