Oh, thanks a lot. Now it's working fine. Now the only problem is that the code is evaluated when calling sympify, and not when calling evalf. Could I ask you what is the way to keep the function lazy? I explain myself better. Since the function SUM has to operate on a database if I have something like that:
>>> SUM('field') + SUM('field') + SUM('field') #not lazy, computes immediately >>> three queries >>> 1234 I'm doing the same operation three times and this is not very good in terms of performances, what I expected would have been: >>> a = SUM('field') + SUM('field') + SUM('field') -> 3SUM('field') # one >>> single query >>> print a >>> 3*SUM('field') >>> print N(a) >>> 1234 just like other functions work. e.g. >>> log(10)+log(10)+log(10) >>> 3*log(10) On Jun 2, 9:38 am, Mateusz Paprocki <matt...@gmail.com> wrote: > Hi, > > On 2 June 2011 09:07, luke <luca.giaco...@gmail.com> wrote: > > > > > > > > > > > Hi eveyone, > > I'm developing an web application which has to interact with "user- > > defined formulas" of some financial kpis. > > I decided to use sympy to have a more solid math engine. > > Basically the input I reiceve is very simple, it might be in the worst > > case something like: > > > kpi -> "(log(sum('production'))*count('sales')/min('spread')" (this > > formula is totally made-up) > > > I defined some functions to interact with the database according to > > the official docs and they seem to be working: > > > For example defining > > > from sympy.core.function import Function > > > class SUM(Function): > > nargs = 2 > > @classmethod > > def eval(cls, arg): > > map = Code("""function () { > > emit("sum",{%(field)s:this.%(field)s}); > > }""" % {'field':arg}) > > reduce = Code(""" > > function(key, values) { > > var sum = 0; > > values.forEach(function(doc) { > > if (doc.%(field)s != undefined){ > > sum += doc.%(field)s; > > } > > }); > > return {%(field)s:sum}; > > };""" % {'field':arg}) > > result = db.people.map_reduce(map, reduce, "myresults") > > return result.find_one()['value'][unicode(arg)] > > > #EOF > > > Then from the command line I can type: > > > >>> print SUM("field") > > >>> 1923 > > Very interesting application. I'm not sure if you are familiar with this, > but staying on the safe side note here that SUM("field") doesn't do exactly > what you expect, but the outcome is fine. Usually, SymPy's functions don't > accept raw string arguments, but sympify() them: > > In [1]: class fun(Function): > ...: nargs = 1 > ...: @classmethod > ...: def eval(cls, arg): > ...: print type(arg) > ...: > ...: > > In [2]: fun('abc') > <class 'sympy.core.symbol.Symbol'> > Out[2]: fun(abc) > > So in eval() you got a symbol not string 'abc', but as str() of a Symbol is > simply the name of the symbol, then this (and your code) works as expected: > > In [3]: print "---%s---" % Symbol('abc') > ---abc--- > > > > > But when I try to use sympify my function doesn't evaluate.. > > > >>> print sympify("SUM('field')").evalf() > > >>> SUM(field) > > >>> N("SUM('field')") > > >>> SUM(field) > > The problem here is that SymPy, precisely speaking sympify(), doesn't know > what SUM() is, because SUM() resides in the global namespace of the > interpreter, which is unknown to sympify(), e.g.: > > In [4]: sympify("whatever(10)") > Out[4]: whatever(10) > > whatever() is unknown to sympify(), so a new Function object is constructed > for it. The same for fun() which I defined above: > > In [6]: sympify("fun(10)") > Out[6]: fun(10) > > To overcome this, pass globals() to sympify(), e.g.: > > In [7]: sympify("fun(10)", globals()) > <class 'sympy.core.numbers.Integer'> > Out[7]: fun(10) > > (in your case this will be sympify("SUM('field')", globals())). > > > > > Am I doing anything wrong? > > Thanks in advance! > > > -- > > You received this message because you are subscribed to the Google Groups > > "sympy" group. > > To post to this group, send email to sympy@googlegroups.com. > > To unsubscribe from this group, send email to > > sympy+unsubscr...@googlegroups.com. > > For more options, visit this group at > >http://groups.google.com/group/sympy?hl=en. > > Mateusz -- You received this message because you are subscribed to the Google Groups "sympy" group. To post to this group, send email to sympy@googlegroups.com. To unsubscribe from this group, send email to sympy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sympy?hl=en.