Opened 6 years ago
Last modified 6 years ago
#18694 new defect
Effectively can't create a symbolic variable named 'lambda'
Reported by: | wonder | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | sage-6.8 |
Component: | symbolics | Keywords: | |
Cc: | Merged in: | ||
Authors: | Reviewers: | ||
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description (last modified by )
This is closely related to #13545, but is not a duplicate.
It is possible to create a variable whose name is 'lambda' by bypassing the SR.var()
function, which prohibits it. However, this leads to crashes later, when that function is used internally:
sage: l = SR.symbol('lambda') sage: l lambda sage: latex(l) \lambda sage: l^2 lambda^2 sage: solve( l^2, l ) --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-5-50da04b743b5> in <module>() ----> 1 solve( l**Integer(2), l ) /usr/local/src/sage/local/lib/python2.7/site-packages/sage/symbolic/relation.pyc in solve(f, *args, **kwds) 796 from sage.symbolic.expression import is_Expression 797 if is_Expression(f): # f is a single expression --> 798 ans = f.solve(*args,**kwds) 799 return ans 800 /usr/local/src/sage/src/sage/symbolic/expression.pyx in sage.symbolic.expression.Expression.solve (build/cythonized/sage/symbolic/expression.cpp:48303)() 10006 from sage.symbolic.relation import string_to_list_of_solutions 10007 > 10008 X = string_to_list_of_solutions(s) # our initial list of solutions 10009 10010 if multiplicities: # to_poly_solve does not return multiplicities, so in this case we end here /usr/local/src/sage/local/lib/python2.7/site-packages/sage/symbolic/relation.pyc in string_to_list_of_solutions(s) 535 from sage.structure.sequence import Sequence 536 from sage.calculus.calculus import symbolic_expression_from_maxima_string --> 537 v = symbolic_expression_from_maxima_string(s, equals_sub=True) 538 return Sequence(v, universe=Objects(), cr_str=True) 539 /usr/local/src/sage/local/lib/python2.7/site-packages/sage/calculus/calculus.pyc in symbolic_expression_from_maxima_string(x, equals_sub, maxima) 1906 global _augmented_syms 1907 _augmented_syms = syms -> 1908 return SRM_parser.parse_sequence(s) 1909 finally: 1910 _augmented_syms = {} /usr/local/src/sage/src/sage/misc/parser.pyx in sage.misc.parser.Parser.parse_sequence (build/cythonized/sage/misc/parser.c:4529)() 539 return expr 540 --> 541 cpdef parse_sequence(self, s): 542 """ 543 Parse a (possibly nested) set of lists and tuples. /usr/local/src/sage/src/sage/misc/parser.pyx in sage.misc.parser.Parser.parse_sequence (build/cythonized/sage/misc/parser.c:4405)() 555 """ 556 cdef Tokenizer tokens = Tokenizer(s) --> 557 all = self.p_sequence(tokens) 558 if tokens.next() != EOS: 559 self.parse_error(tokens) /usr/local/src/sage/src/sage/misc/parser.pyx in sage.misc.parser.Parser.p_sequence (build/cythonized/sage/misc/parser.c:5117)() 619 obj = self.p_eqn(tokens) 620 elif token == '[': --> 621 obj = self.p_list(tokens) 622 elif token == '(': 623 obj = self.p_tuple(tokens) /usr/local/src/sage/src/sage/misc/parser.pyx in sage.misc.parser.Parser.p_list (build/cythonized/sage/misc/parser.c:5436)() 651 if token != '[': 652 self.parse_error(tokens, "Malformed list") --> 653 all = self.p_sequence(tokens) 654 token = tokens.next() 655 if token != ']': /usr/local/src/sage/src/sage/misc/parser.pyx in sage.misc.parser.Parser.p_sequence (build/cythonized/sage/misc/parser.c:5207)() 628 return all 629 else: --> 630 obj = self.p_eqn(tokens) 631 PyList_Append(all, obj) 632 token = tokens.next() /usr/local/src/sage/src/sage/misc/parser.pyx in sage.misc.parser.Parser.p_eqn (build/cythonized/sage/misc/parser.c:6006)() 718 a != b 719 """ --> 720 lhs = self.p_expr(tokens) 721 cdef int op = tokens.next() 722 if op == '=': /usr/local/src/sage/src/sage/misc/parser.pyx in sage.misc.parser.Parser.p_expr (build/cythonized/sage/misc/parser.c:6355)() 758 # Note: this is left-recursive, so we can't just recurse 759 cdef int op --> 760 operand1 = self.p_term(tokens) 761 op = tokens.next() 762 while op == '+' or op == '-': /usr/local/src/sage/src/sage/misc/parser.pyx in sage.misc.parser.Parser.p_term (build/cythonized/sage/misc/parser.c:6618)() 792 # Note: this is left-recursive, so we can't just recurse 793 cdef int op --> 794 operand1 = self.p_factor(tokens) 795 op = tokens.next() 796 if op == NAME and self.implicit_multiplication: /usr/local/src/sage/src/sage/misc/parser.pyx in sage.misc.parser.Parser.p_factor (build/cythonized/sage/misc/parser.c:7036)() 835 else: 836 tokens.backtrack() --> 837 return self.p_power(tokens) 838 839 # power ::= (atom | atom!) ^ factor | atom | atom! /usr/local/src/sage/src/sage/misc/parser.pyx in sage.misc.parser.Parser.p_power (build/cythonized/sage/misc/parser.c:7190)() 863 864 """ --> 865 operand1 = self.p_atom(tokens) 866 cdef int token = tokens.next() 867 if token == '^': /usr/local/src/sage/src/sage/misc/parser.pyx in sage.misc.parser.Parser.p_atom (build/cythonized/sage/misc/parser.c:7902)() 925 else: 926 tokens.backtrack() --> 927 return self.variable_constructor(name) 928 elif token == '(': 929 expr = self.p_expr(tokens) /usr/local/src/sage/local/lib/python2.7/site-packages/sage/calculus/calculus.pyc in _find_Mvar(name) 2097 """ 2098 if name[:10] == "_SAGE_VAR_": -> 2099 return var(name[10:]) 2100 res = _augmented_syms.get(name) 2101 if res is not None and not isinstance(res, Function): /usr/local/src/sage/src/sage/symbolic/ring.pyx in sage.symbolic.ring.var (build/cythonized/sage/symbolic/ring.cpp:10931)() 988 ValueError: The name "3" is not a valid Python identifier. 989 """ --> 990 return SR.var(name, **kwds) 991 992 def is_SymbolicVariable(x): /usr/local/src/sage/src/sage/symbolic/ring.pyx in sage.symbolic.ring.SymbolicRing.var (build/cythonized/sage/symbolic/ring.cpp:8883)() 611 return e 612 --> 613 cpdef var(self, name, latex_name=None, domain=None): 614 """ 615 Return the symbolic variable defined by x as an element of the /usr/local/src/sage/src/sage/symbolic/ring.pyx in sage.symbolic.ring.SymbolicRing.var (build/cythonized/sage/symbolic/ring.cpp:8557)() 664 for s in names_list: 665 if not isidentifier(s): --> 666 raise ValueError('The name "'+s+'" is not a valid Python identifier.') 667 668 if len(names_list) == 0: ValueError: The name "lambda" is not a valid Python identifier. sage:
If the reason for prohibiting this name is that it can't be used when var()
creates a Python global variable, that prohibition should be enforced in var()
, not in SR.var()
.
Change History (11)
comment:1 Changed 6 years ago by
- Description modified (diff)
comment:2 Changed 6 years ago by
comment:3 Changed 6 years ago by
This ticket is about using lambda
as a math symbol, not a Python variable name. That's why the Python variable name in the included code snippet is not lambda
. It's standard mathematical practice to use lambda
as a symbol, and Sage should support it as fully as possible.
comment:4 Changed 6 years ago by
I maybe agree. SR.var
doesn't particularly inject a binding into a python scope, so it doesn't necessarily need to check whether things are python identifiers.
That said, for the sanity of the system it might be a good idea to make some checks on what kind of math symbols we allow. These things tend to end up in strings to various interfaces (although we wouldn't really need to do that for maxima, but we still do). It might even be that we end up "eval"-ing expressions in python, in which case python identifiers shouldn't be allowed.
comment:5 follow-up: ↓ 6 Changed 6 years ago by
Is that eval
-ing really a good thing to do? Given that SR
expressions are not python expressions - they include things like "integral" and "D[0]" - it seems like any code that tries to interpret the string value of an SR
expression as a python expression would be a serious bug, whether it collides with names like lambda
or not. I imagine there must be some kind of translation step from SR
to python. Surely that step could include translating "lambda" to "SAGE_SR_SYMBOL_lambda" or whatever.
comment:6 in reply to: ↑ 5 Changed 6 years ago by
Replying to wonder:
Is that
eval
-ing really a good thing to do? Given thatSR
expressions are not python expressions - they include things like "integral" and "D[0]" - it seems like any code that tries to interpret the string value of anSR
expression as a python expression would be a serious bug,
I don't know. I think the standard representation we use is valid python syntax (modulo keyword clashes), and otherwise it would be easy to render them into valid python syntax. I'm not sure if we ever do. The fact is symbolic expressions DO get rendered as strings in various languages. Even in maxima, the whole SAGE_VAR wrapping thing is relatively recent. We have various implicit restrictions on what symbols survive the various translation processes. I'm not entirely sure whether lambda is one of those implicit restrictions.
comment:7 follow-up: ↓ 9 Changed 6 years ago by
I'm not entirely sure whether lambda is one of those implicit restrictions.
Would it be helpful to relax the restriction and see if the tests fail?
I think the standard representation we use is valid python syntax (modulo keyword clashes),
Out of curiosity, how is "D[0](f)(x)" made into valid python syntax?
comment:8 Changed 6 years ago by
Would it be helpful to relax the restriction and see if the tests fail?
No, of course not. New tests would have to be written. Never mind that.
comment:9 in reply to: ↑ 7 Changed 6 years ago by
Replying to wonder:
Out of curiosity, how is "D[0](f)(x)" made into valid python syntax?
It already is: you don't get a syntax error if you type it into sage.
If you want to ensure it executes properly in addition to being valid syntax you have to bind D to an object that puts the information in the right places. I posted this example elsewhere but I can't locate it right now:
class Dclass(object): def __getitem__(self,a): if isinstance(a,tuple): L=[i for i in a] else: L=[a] def derivator(f): return sage.symbolic.operators.FDerivativeOperator(f,L) return derivator D=Dclass()
With this binding, you get:
sage: D[0,0,0](sin)(x) -cos(x)
EDIT: Found the original code (it's painful how google results now depend on which computer you use!) in this sage-devel discussion
comment:10 Changed 6 years ago by
Note also that lambda_
does most of what you want, if I recall correctly.
comment:11 Changed 6 years ago by
Note also that lambda_ does most of what you want, if I recall correctly.
@kcrisman thanks, that's good to know.
If you want to ensure it executes properly in addition to being valid syntax you have to bind D to an object
@nbruin thanks - this seems to say that SR
expressions can be parsed as python expressions but not eval
ed, since this operator isn't defined in Sage as is.
lambda
is a reserved keyword in Python, so just likeand
ordef
it shouldn't be used as a variable name.