New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symbol.__call__ should not create a Function #3539

Closed
certik opened this Issue Oct 27, 2007 · 95 comments

Comments

Projects
None yet
8 participants
@certik
Copy link
Member

certik commented Oct 27, 2007

sympycore now has a working implementation of how to work with unapplied
functions easily. There are related bugs in sympy now, for example:

In [1]: a = Symbol("exp")

In [2]: a(z)
Ignoring redefinition of exp: <class
'sympy.functions.elementary.exponential.exp'> defined earlier than <class
'sympy.core.function.exp'>
Out[2]: exp(z)

There should be one and only one way of creating new functions, be it
Function("something"), or Symbol("something")(x), or whatever, that's fine,
as long as it's just one way.

Let's implement that in sympy and fix all related issues.

Original issue for #3539: http://code.google.com/p/sympy/issues/detail?id=440

Original author: https://code.google.com/u/104039945248245758823/

@pearu

This comment has been minimized.

Copy link

pearu commented Oct 27, 2007

The reason that Symbol implements **call** is to make
parsing work for strings like `f(x)+1`.

Parser does not know what the atomic `f` should be and it assumes
that it is a Symbol. And later when `f` is called, the Symbol.**call**
creates a proper undefined function instance for `f`.

Otherwise, Function('f') should be the only way to create
new functions. One should never use Symbol.**call**. May be
the parser should temporarily set Symbol.**call** method
and later remove it to avoid codes like `Symbol('exp')(1)`
but that would add extra code and under estimates users
ability to read documentation..

Parsing strings like 'exp(x)' used to work when `exp` was a singleton.
When we stopped using singletons, the code that dealt with mapping
symbols `exp`, `log`, to functions was not updated.

The patch in issue 3438 works. But I think this is ugliest way 
(using try,silent except,and eval combination) to fix this issue;)
Codelet
{{{
         obj = getattr(sympy, self.string, None)
         if obj is not None:
             return obj
         return Basic.Symbol(self.string)
}}}
should be fine.

Referenced issues: #3438

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c1

Original author: https://code.google.com/u/pearu.peterson/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 27, 2007

Completely agree, feel free to improve the patch. :)

> new functions. One should never use Symbol.**call**. May be
> the parser should temporarily set Symbol.**call** method

Agree.

How about using eval(“exp(x)”, sympy.dict) instead of parse in sympify? Isn’t it
shorter && easier to maintain?

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c2

Original author: https://code.google.com/u/104039945248245758823/

@pearu

This comment has been minimized.

Copy link

pearu commented Oct 27, 2007

If `x` is undefined in sympy namespace then you'll get NameError.

The point of having a parser is 
- to avoid declaring symbolic variables
- to use syntax that Python does not support, eg
  'a and b' is parsed to `And(a, b)`.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c3

Original author: https://code.google.com/u/pearu.peterson/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 27, 2007

I see. Do we need preparsing at all? :) 

> - to avoid declaring symbolic variables

This could be solved somehow using eval.

> - to use syntax that Python does not support, eg
>   'a and b' is parsed to `And(a, b)`.

This couldn't be solved with eval(). Why do you need to parse "a and b"? This is
basically extending the syntax of Python. Should this be in the sympy.core? Generally
I don't like any kinds of preparsing, because I think it only makes things
complicated, but well justified cases are ok. 

The "a and b" case seems to me like the mathematica parser (which can also be in
sympy, if it was done nicely).

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c4

Original author: https://code.google.com/u/104039945248245758823/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 27, 2007

Btw, I committed your improvement to the patch.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c5

Original author: https://code.google.com/u/104039945248245758823/

@pearu

This comment has been minimized.

Copy link

pearu commented Oct 27, 2007

What do you mean by preparsing?

Recall that parser is used only when sympify argument
is a string containing an expression. One does not need
to use parsing at all if one does not like it.

parser is not equivalent to idiom of executing eval('<expression>').
Otherwise why would one write

  sympify('1+exp(x)')

if one can write

  1 + exp(x)

?

I personally use parser only as a convinent way to quickly
construct symbolic expressions. Compare

> > > from sympy import *
> > > expr = sympify('(1/2+x)**2')

to

> > > from sympy import *
> > > x = Symbol('x')
> > > expr = (Rational(1,2)+x)**2

How can you automatically declare x=Symbol('x') in
executing

  eval('1+exp(x)')

? eval will raise NameError and I don't know any way
to enhance builtin eval function with custom exception
handler that would catch NameError and would create
an Symbol instance.

Note that parsing '3/4' to Rational(3,4) is also an extension
to Python syntax. So, parsing 'a and b' to And(a, b) falls
into the same category, imho.

I think it is OK to introduce extensions to Python syntax
in parser provided that it does not change Python syntax.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c6

Original author: https://code.google.com/u/pearu.peterson/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 28, 2007

> What do you mean by preparsing?

I used a wrong word - I just meant parsing, instead of using the python syntax.

> How can you automatically declare x=Symbol('x') in
> executing
>  eval('1+exp(x)')

For example:

import sympy
mydict = {}
mydict.update(sympy.abc.**dict**)
mydict.update(sympy.**dict**)
print eval("1+exp(x)+exp(y)", mydict)

This will be done in sympify. The huge advantage of this is that when we change
something in SymPy, we don't have to update the parser.

> Note that parsing '3/4' to Rational(3,4) is also an extension
> to Python syntax. So, parsing 'a and b' to And(a, b) falls
> into the same category, imho.

Well, that's right. I tend not to like either. But typing Rational(3)/4 is annoying
for sure.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c7

Original author: https://code.google.com/u/104039945248245758823/

@sympy-issue-migrator

This comment has been minimized.

Copy link

sympy-issue-migrator commented Oct 29, 2007

In fact, I am in favour of Pearu's suggestion to continue the support of sympify()
since this approach is much easier to use (you don't have to write "from sympy import
*" which whould otherwise result in a NameError with Python not being aware of
functions like log, exp, etc.).
Moreover using sympify() involves checking whether the given expression can be
regarded as valid or not (resulting in a ValueError).

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c8

Original author: https://code.google.com/u/117027974304931495287/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 29, 2007

I think we misunderstood each other a little bit: there is no doubt sympify() is
needed - a central function for converting anything to SymPy classes, otherwise you
wouldn't even be able to write "1+x", you would have to write "Integer(1)+x" instead. 

The question is, whether we need the sympy.core.parser, e.g. whether the line in
sympy.core.basic.py:257:

```
       try:
            return parser.Expr(a).tosymbolic()
        except:
            pass
```

cannot rather be changed to something like:

try:
    import sympy
    mydict = {}
    mydict.update(sympy.abc.**dict**)
    mydict.update(sympy.**dict**)
    return eval("1+exp(x)+exp(y)", mydict)
except:
    pass

and get rid of sympy.core.parser (or move it to modules, as an optional tool for
implementing new syntaxes etc. etc).

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c9

Original author: https://code.google.com/u/104039945248245758823/

@navytux

This comment has been minimized.

Copy link

navytux commented Oct 29, 2007

It seems, parsing is only better than pure eval when rationals are used: '1/2'
instead of 'Rational(1)/2'.

All other issues like symbol not being decalred are already addressed in comment #7.

I've tried to deal with inconveience of Rational(1)/2. Basically I tweak a bit
numebers handling in standard Python compiler package.

Resume: eval + a bit of tweaks + standard Python parser are enough.

The proof-of-concept program is attached.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c10

Original author: https://code.google.com/u/111152560333599832822/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 29, 2007

Haha, that interesting.

You forgot to put there a few changes:

"import compiler" at the beginning and the last line should be:

print '%-20r: %r' % (src, eval(sympy_expr_compile(src)))

The output of the last cycle is:

'1'                 : 1
'1/2'               : 1/2
'5/8'               : 5/8
'5/8*_12'           : 5/68719476736
'sin(pi/8)_(2/3)'   : (2/3)_sin((1/8)_pi)

'1'                 : One(1)
'1/2'               : Half(1, 2)
'5/8'               : Rational(5, 8)
'5/8*_12'           : Rational(5, 68719476736L)
'sin(pi/8)_(2/3)'   : Mul(Rational(2, 3), sin(Mul(Rational(1, 8), Pi())))

The gist of the idea is here:

class SymPyTransformer(Transformer):
    """Transform Python expressions into AST, inject 'Rational' subtrees in place of
numbers"""

```
def atom_number(self, nodelist):
    n = Transformer.atom_number(self, nodelist)

    return CallFunc(Name('Rational'), [n])
```

The rest are just hooks how to get it injected into the python framework, right?

One nice thing about it is, that it is ~50 lines of code, compared to
sympy.core.parser, that has ~900 lines. I think if the same functionality can be
achieved by 18x shorter code, why not to do it?

I think the last issue, that consensus haven't been achieved so far is the "a and b"
-> "And(a,b)". I, speaking for myself now, I am fine with writting And(a,b). I like
Python and I like Python syntax, no need to devise something new. I suggest you to
read this thread for overloading **and**: http://mail.python.org/pipermail/python-list/2007-May/443143.html So to sum it up - I think And(a,b) or (a & b) is perfectly convenient for me and this
works in Python. Rational(1)/2 is not convenient, one solution is the Kirill's patch,
the other is Pearu's parsing module, the third is to do nothing. 
Another option is to introduce some shorthand for Rational, like R.  R(1)/2 is much
easier to type.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c11

Original author: https://code.google.com/u/104039945248245758823/

@pearu

This comment has been minimized.

Copy link

pearu commented Oct 30, 2007

`a&b` is not a convinient way to represent logical `And(a,b)` because
Python `&` operator has a "wrong" precedence compared to arithemtic operations
and it has different action (bitwise-and) on integers.
For example, (if we ever are going to use `<` operator for `Less` then)
Python evaluates

  a & b + 1 < 0

as

  ((a & b) + 1) < 0

which is obviosly not what an user would expect for an And operator:

  a and b+1 < 0

ahould evaluate as

  a and ((b + 1) < 0)

.

Using AST for parsing python expressions if fine, even `and` operator could be
overloaded by this.

The downside is that one will be restricted to Python syntax and it is quite messy
to work with AST (I have used AST trees for parsing symbolic expressions some
years ago).

This was also one of the reasons of writing a parser from scratch
so that it could be enhanced with whatever features one needs for symbolic
manipulations. The `a and b` is just one example, the other one is
`a union b` for `Union(a,b)`. Also, the parser can be easily enhanced to
read C or Fortran expressions to sympy expressions. And eventually, we also
need C/Fortran expression writers.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c12

Original author: https://code.google.com/u/pearu.peterson/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 30, 2007

You are right with the &. 

You are right, that AST is probably messy, but I thought we just need to fix the 1/2
problem and maybe "a and b" problem. At least I think that sympify("...") should just
follow the Python syntax, with the exception of a few possible additions. I think
this can be handled using AST more easily. The important question is of the
maintainability - and as I said, 60lines of code are definitely easier to maintain
than 900 lines.

As to the general parser - yes, being able to read/write to/from C/Fortran is very
useful (and not only C/Fortran, also Maple/Mathematica, any other system). But I
believe such a parser should sit in modules and the core shouldn't be depending on
it. Also maybe how about using some library for parsing?

I have a good experience with pyparsing: http://pyparsing.wikispaces.com/ But there are many others (faster/slower, harder/easier to use, ...). I think it's
better to reuse some library like this, so that the parser is easier to understand
and maintain, rather to write our own from scratch. Or is there some problem with
those parsing libraries in Python?

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c13

Original author: https://code.google.com/u/104039945248245758823/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 30, 2007

Nice link is the sample chapter from pyparsing website: http://my.safaribooksonline.com/9780596514235/conclusion#X2ludGVybmFsX1RvYz94bWxpZD05NzgwNTk2NTE0MjM1L3doYXRfbWFrZXNfcHlwYXJzaW5nX3NvX3NwZWNpYWw= I think this is how any parser should look like, following the zen of python.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c14

Original author: https://code.google.com/u/104039945248245758823/

@pearu

This comment has been minimized.

Copy link

pearu commented Oct 30, 2007

So, you are saying that parsing library in sympy is badly written
that we should use some other library;)

Most parsing libraries assume contemporary syntax rules but
Fortran 77 syntax does not follow these rules, eg. one
can write a valid Fortran 77 program without ever using
any whitespace characters.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c15

Original author: https://code.google.com/u/pearu.peterson/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 30, 2007

No, what I am saying is that I would like to discuss (without emotions:) all
possibilities, see pros and cons of each option and then choose the best one. 

Right, definitely one requirement on the parsing library (be it our own, e.g. the one
in sympy, or some other) is to parse Fortran 77 expression syntax. 

But I think e.g. pyparsing should be able to handle that.

But that's the parsing library. Do you want to call it from sympify? Or do you agree
to parse just Python syntax in sympify and leave all this parsing of other languages
to modules?

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c16

Original author: https://code.google.com/u/104039945248245758823/

@pearu

This comment has been minimized.

Copy link

pearu commented Oct 30, 2007

That's resonable argument. sympify does not need to be parser, it should
be able to deal with python expressions and hence with strings containing python
expressions. Language parsers should probably go to interface subpackage.

Btw, sympify should be able to handle also strings like 'abc+1' to
`Symbol('abc')+1`, the abc module does not handle this.

Can pyparsing handle Fortran expression `a.and.b`?

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c17

Original author: https://code.google.com/u/pearu.peterson/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 30, 2007

> Btw, sympify should be able to handle also strings like 'abc+1' to

> `Symbol('abc')+1`, the abc module does not handle this.

Yeah - the general idea being to use the eval() code above, this will parse fine all
sympy things plus symbols from the sympy.abc module. And then everything else that
remains will be just Symbols. Let's see if this could be achieved easily using the
AST method above. If not, then of course this would be a reason to use our own parser.

> Can pyparsing handle Fortran expression `a.and.b`?

I think it does, you can parse any grammar, not just whitespaces.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c18

Original author: https://code.google.com/u/104039945248245758823/

@pearu

This comment has been minimized.

Copy link

pearu commented Oct 30, 2007

If sympify can handle `abc+1` then the abc.py module will become redudant
as it defines only Symbol instances.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c19

Original author: https://code.google.com/u/pearu.peterson/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 30, 2007

But as Linus says "talk is cheap, show me the code", your parser works and does the
job. I am just saying one should be aware of the other (maybe simpler, maybe not)
possibilities to tackle the problem. 

Anyway, when we fix the "abc" -> Symbol using a simple AST, we can move parsing to
modules.

BTW, the "abc" -> Symbol doesn't seem to be implemented in parsing either:

In [1]: sympify(1+x)
Out[1]: 1 + x

## In [2]: sympify(1+xs)

exceptions.NameError                                 Traceback (most recent call last)

/home/ondra/sympy/<ipython console> 

NameError: name 'xs' is not defined

## In [3]: sympify(1+abc)

exceptions.TypeError                                 Traceback (most recent call last)

/home/ondra/sympy/<ipython console> 

TypeError: unsupported operand type(s) for +: 'int' and 'module'

Note that in [3], the problem is whether abc should be a Symbol or the name of the
module.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c20

Original author: https://code.google.com/u/104039945248245758823/

@pearu

This comment has been minimized.

Copy link

pearu commented Oct 30, 2007

You forget quotes:) Try
  sympify('1+abc')

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c21

Original author: https://code.google.com/u/pearu.peterson/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 30, 2007

Haha. :) Yeah, but still:

## In [1]: sympify("1+abc")

exceptions.ValueError                                Traceback (most recent call last)

/home/ondra/sympy/<ipython console> 

/home/ondra/sympy/sympy/core/basic.py in sympify(a, sympify_lists)
    258             except:
    259                 pass
--> 260         raise ValueError("%r is NOT a valid SymPy expression" % a)
    261 
    262     @Memoizer('Basic', MemoizerArg((type, type(None), tuple), name='type'),
return_value_converter = lambda obj: obj.copy())

ValueError: '1+abc' is NOT a valid SymPy expression

In [2]: sympify("1+abcx")
Out[2]: 1 + abcx

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c22

Original author: https://code.google.com/u/104039945248245758823/

@pearu

This comment has been minimized.

Copy link

pearu commented Oct 30, 2007

That's a bug introduced recently to parser.py. Here is a fix:

class Identifier(StringBase):
    ...
    def tosymbolic(self, commutative=True):
        obj = Basic.singleton.get(self.string)
        if obj is not None:
            return obj()
        import sympy
        obj = getattr(sympy, self.string, None)
        if isinstance(obj, sympy.Basic):
            return obj
        return Basic.Symbol(self.string)

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c23

Original author: https://code.google.com/u/pearu.peterson/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 30, 2007

It doesn't work.

$ hg di
diff -r 611551980c83 sympy/core/parser.py
--- a/sympy/core/parser.py      Tue Oct 30 02:54:19 2007 +0100
+++ b/sympy/core/parser.py      Tue Oct 30 12:12:03 2007 +0100
@@ -652,7 +652,7 @@ class Identifier(StringBase):
             return obj()
         import sympy
         obj = getattr(sympy, self.string, None)
-        if obj is not None:
-        if isinstance(obj, sympy.Basic):
           return obj
       return Basic.Symbol(self.string)

$ py.test sympy/core/tests/test_functions.py
inserting into sys.path: /home/ondra/py-dist
============================= test process starts ==============================
executable:   /usr/bin/python  (2.4.4-final-0)
using py lib: /home/ondra/py-dist/py <rev 47566>

sympy/core/tests/test_functions.py[14] ...........F.f

---

_____________________________ entrypoint: test_439 _____________________________

```
def test_439():
    v = sympify("exp(x)")
    x = Symbol("x")
    assert v == exp(x)
    assert type(v) == type(exp(x))
```

E       assert str(type(v)) == str(type(exp(x)))

> ```
>   assert "<class 'sympy.core.function.exp'>" == "<class
> ```
> 
> 'sympy.functions.elementary.exponential.exp'>"
>          +  where "<class 'sympy.core.function.exp'>" = str(<class
> 'sympy.core.function.exp'>)
>          +    where <class 'sympy.core.function.exp'> = type(exp(x))
>          +  and   "<class 'sympy.functions.elementary.exponential.exp'>" = str(<class
> 'sympy.functions.elementary.exponential.exp'>)
>          +    where <class 'sympy.functions.elementary.exponential.exp'> = type(exp(x))
>          +      where exp(x) = exp(x)

[/home/ondra/sympy/sympy/core/tests/test_functions.py:141]
- \- - - - - - - - - - - -  test_439: recorded stdout - - - - - - - - - - - - - -
  Ignoring redefinition of exp: <class 'sympy.functions.elementary.exponential.exp'>
  defined earlier than <class 'sympy.core.function.exp'>

---

========= tests finished: 12 passed, 1 xfail, 1 failed in 0.17 seconds =========
DO _NOT_ COMMIT!

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c24

Original author: https://code.google.com/u/104039945248245758823/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 30, 2007

btw here is the test that should be passed by the new fix:

diff -r 611551980c83 sympy/core/tests/test_functions.py
--- a/sympy/core/tests/test_functions.py        Tue Oct 30 02:54:19 2007 +0100
+++ b/sympy/core/tests/test_functions.py        Tue Oct 30 12:14:01 2007 +0100
@@ -139,3 +139,11 @@ def test_439():
     assert v == exp(x)
     assert type(v) == type(exp(x))
     assert str(type(v)) == str(type(exp(x)))
+
+def test_440():
-    v1 = sympify("1+abcx")
-    v2 = sympify("1+abc")
-    x1 = Symbol("abcx")
-    x2 = Symbol("abc")
-    assert v1 == 1+x1
-    assert v2 == 1+x2

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c25

Original author: https://code.google.com/u/104039945248245758823/

@pearu

This comment has been minimized.

Copy link

pearu commented Oct 30, 2007

The test does not pass because in sympy

  isinstance(exp, Basic) is False

and that is because FunctionClass is not
derived from Basic as it should be (sympycore
does things correctly here).
So, the test should pass when function support code
is updated properly.

In a mean time, I guess that the following
codelet should fix it:

  if isinstance(obj, (Basic, Basic.**metaclass**)):
    return obj

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c26

Original author: https://code.google.com/u/pearu.peterson/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 30, 2007

Yes. This is what this issue is about, to polish these things in sympy. I'll leave it
as is now and when I, or someone else finds time, we should fix all these things once
and for all.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c27

Original author: https://code.google.com/u/104039945248245758823/

@navytux

This comment has been minimized.

Copy link

navytux commented Oct 30, 2007

It is possible to have Symbols by default.

The idea is to tweak locals when doing eval. This is supported since Python 2.4 so 
is ok.

We just use some form of "default dictionary", which creates default values if they 
are not found.

'1'                 : 1
'1/2'               : 1/2
'5/8'               : 5/8
'5/8*_12'           : 5/68719476736
'sin(pi/8)_(2/3)'   : (2/3)_sin((1/8)_pi)
'1+x'               : 1 + x
'exp(school_mean)'  : exp(school_mean)

'1'                 : One(1)
'1/2'               : Half(1, 2)
'5/8'               : Rational(5, 8)
'5/8*_12'           : Rational(5, 68719476736L)
'sin(pi/8)_(2/3)'   : Mul(Rational(2, 3), sin(Mul(Rational(1, 8), Pi())))
'1+x'               : Add(One(1), Symbol('x'))
'exp(school_mean)'  : exp(Symbol('school_mean'))

Code attached.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c28

Original author: https://code.google.com/u/111152560333599832822/

@pearu

This comment has been minimized.

Copy link

pearu commented Oct 31, 2007

I have implemented sympify function using Python compiler
in sympycore and the basic idea from sympyexpr.py. Check it
out in http://sympycore.googlecode.com/svn/trunk/sympy/core/sympify.py Few examples:

> > > sympify('2/3+abc')
> > > 2/3 + abc
> > > sympify('Exp(x)+1.34')
> > > 1.34 + Exp(x)
> > > sympify('lambda x,y: x_y')
> > > Lambda((_x, _y), _y__x)

PS: this code assumes sympycore where all function names are CamelCase.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c29

Original author: https://code.google.com/u/pearu.peterson/

@certik

This comment has been minimized.

Copy link
Member

certik commented Oct 31, 2007

The code looks very good and short. Now someone needs to implement it in sympy. Till
sage days 6, I am very busy. But maybe I'll have some time to implement these things
in there.

Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c30

Original author: https://code.google.com/u/104039945248245758823/

@asmeurer

This comment has been minimized.

Copy link
Member

asmeurer commented Apr 22, 2012

**Blocking:** 6335  

Referenced issues: #6335
Original comment: http://code.google.com/p/sympy/issues/detail?id=440#c96
Original author: https://code.google.com/u/asmeurer@gmail.com/

@certik certik added imported labels Mar 7, 2014

@jcrist jcrist removed the Priority: High label Apr 17, 2015

@bjodah

This comment has been minimized.

Copy link
Member

bjodah commented Feb 7, 2016

Possibly related: gh-9064

cbm755 added a commit to cbm755/sympy that referenced this issue Aug 8, 2018

cbm755 added a commit to cbm755/sympy that referenced this issue Aug 10, 2018

parser: test that `S('f(x)')` still works
After the changes removing Symbols becoming Functions from
Issue sympy#3539, I'm not sure this was tested anywhere.

cbm755 added a commit to cbm755/sympy that referenced this issue Aug 10, 2018

parser: fix imports and test that `S('f(x)')` still works
After the changes removing Symbols becoming Functions from
Issue sympy#3539, I'm not sure this was tested anywhere.  Fix imports so
that Symbol is available (and use that instead of `sympy.Symbol`).

cbm755 added a commit to cbm755/sympy that referenced this issue Aug 10, 2018

parser: fix imports and test that `S('f(x)')` still works
After the changes removing Symbols becoming Functions from
Issue sympy#3539, I'm not sure this was tested anywhere.  Fix imports so
that Symbol is available (and use that instead of `sympy.Symbol`).

@asmeurer asmeurer closed this in 18d589a Aug 17, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment