When one writes g(f, x) it creates two variables f and x, and your
original f is gone. I'm not sure what the best fix is here... There
is also the counter-intuitive
sage: f = var('f')
sage: f(3)
3
- Robert
That can't be done (yet). You can do
def g(f, x):
return x+1
But then it's a Python function, not a calculus function.
- Robert
To add a little more detail here: I'm not sure you're understanding
what's going on in your example.
Consider this:
sage: E = (x+3)*sin(x)
sage: E(5)
8*sin(5)
sage: E.subs(x=5)
8*sin(5)
So E(5) is treated as a shorthand for E.subs(x=5).
Now if we consider:
sage: var('f x')
(f, x)
sage: f(x+3)
x + 3
sage: f.subs(f=x+3)
x + 3
it's the exact same thing.
This causes trouble in other situations, as well; if you wanted
multiplication, but you left off the '*' symbol:
sage: x(x+1)
x + 1
sage: x.subs(x=x+1)
x + 1
I've argued before that this shorthand should be removed because it's
too confusing, but I haven't managed to convince enough people, so
it's still there. (The shorthand isn't there in the new, Pynac-based
symbolics, so when we switch over to that system, this particular
source of confusion will be gone.)
Carl
It goes by alphabetical order by default:
sage: E.variables()
(bar, foo)
--Mike
Yes, this is strange, and one thing that I'm glad is going away. (I
like the f(...) notation, but only if there's no ambiguity to be
resolved.)
- Robert
I'm not sure what you're trying to say here. Are you saying that
since x(x+1) has no other useful meaning, we might as well make it
mean x+1?
I hope that the shorthand does not come back, but I don't know that
any sort of final decision has been made. I don't think it's
technically difficult to implement, I just think it's a bad idea.
> Anyway, as several have commented, this discussion has taken place
> many times before, but having to use
> sage: f(x)=x^2
> instead of
> sage: f=x^2
> many times for single-variable symbolic expressions could be very
> annoying in the long run, IMHO. Let's not be stultified by trying to
> solve computer problems when this is mathematical software; the
> distinction between symbolic and callable-symbolic seems different to
> me than e.g. formal power series versus actually convergent ones.
> FWIW.
I don't understand this paragraph at all. What problem are you
talking about? The problem I see is that people are confused when
x(x+1) gives them (x+1); I wouldn't call that a computer problem
exactly.
Carl
I also think it is a bad idea, and I believe that Burcin and I decided
(as a "final decision") that the shorthand will not be in the new
Pynac. I think it was a condition for Burcin to keep working on the
new Pynac in fact :-).
I'm amazed that implicit calling of symbolic expressions is still in
Sage. I knew that it absolutely *had* to go while watching repeatedly
the problems it causes in the high school students in a summer course
I taught using Sage over a year ago.
>> Anyway, as several have commented, this discussion has taken place
>> many times before, but having to use
>> sage: f(x)=x^2
>> instead of
>> sage: f=x^2
>> many times for single-variable symbolic expressions could be very
>> annoying in the long run, IMHO. Let's not be stultified by trying to
>> solve computer problems when this is mathematical software; the
>> distinction between symbolic and callable-symbolic seems different to
>> me than e.g. formal power series versus actually convergent ones.
>> FWIW.
>
> I don't understand this paragraph at all. What problem are you
> talking about? The problem I see is that people are confused when
> x(x+1) gives them (x+1); I wouldn't call that a computer problem
> exactly.
Just out of curiosity, do you think we should also get rid of this?
sage: R.<x> = ZZ[]
sage: x(x+1)
x + 1
-- William
>> Anyway, as several have commented, this discussion has taken place
>> many times before, but having to use
>> sage: f(x)=x^2
>> instead of
>> sage: f=x^2
>> many times for single-variable symbolic expressions could be very
>> annoying in the long run, IMHO. Let's not be stultified by trying to
>> solve computer problems when this is mathematical software; the
>> distinction between symbolic and callable-symbolic seems different to
>> me than e.g. formal power series versus actually convergent ones.
>> FWIW.
>
> I don't understand this paragraph at all. What problem are you
> talking about? The problem I see is that people are confused when
> x(x+1) gives them (x+1); I wouldn't call that a computer problem
> exactly.
I agree with Carl. I can't count how many times I've thought I would be
annoyed by being more explicit (i.e., saying f(x)=x^2 instead of f=x^2),
but it turned out to be not that bad. I also can't count the number of
times that I've been glad and relieved that I was explicit when I came
back and read or modified my code (i.e., suppose I want to change
f=x^2+1 to f=x^2+c to analyze what happens when c changes? Now I have
to go back through and change all of my code from f(1) to f(x=1)!).
I very much support what pynac is doing, which to my understanding, is this:
f(x,y) = x^2+y # explicitly ordered parameters
f(-1,2) then gives 3
f=x^2+y # no explicit parameters for f, so they must be specified
f(x=-1,y=2) then gives 3
f(-1,2) gives an error
f.subs(x=-1,y=2) then gives 3
I think having x(x+1) return x+1 is a far greater annoyance than having
to explicitly write f(x)=x;f(x+1) or x.subs(x=x+1) or even x(x=x+1), all
of which would hardly be written as an innocent-looking mistake.
I'm always telling my students to not leave off the "dx" in an integral,
even though there is only one variable, since it is so very important
when we introduce other parameters or move to multivariable calculus. I
try to use d/dt notation for derivatives because it is more explicit
about what variable I'm dealing with, even if initially we only see one
variable. I think there are great benefits for three more keystrokes
(i.e., "(x)") in the definition of a function if it makes things much
more explicit and easy for anyone to understand and takes away
innocent-looking errors that almost surely will trip new users up.
Gee, the last few paragraphs sound a lot more rant-like than I intended.
I wasn't trying to pick on anyone. I guess I was just realizing how
strongly I support what I think are the conventions introduced by pynac.
Thanks,
Jason
Ouch, that's a tougher question, since I actually use that construct :)
But since I don't want to be a total hypocrite, I'm going to say yes,
we should get rid of it. (With a deprecation message -- eventually to
be replaced by an error message -- that gives the recommended
replacement.)
So, should I prepare patches that deprecate implicit calling of
symbolics and of polynomials? (Would they be likely to be accepted?)
Carl
:-) One possibility would be that if f is a polynomial over a ring R, then
f(a) is defined when a is canonically convertible to R, but raises an error
otherwise. Then x(x+1) would give an error, but x(5) would give 5.
> But since I don't want to be a total hypocrite, I'm going to say yes,
> we should get rid of it. (With a deprecation message -- eventually to
> be replaced by an error message -- that gives the recommended
> replacement.)
>
> So, should I prepare patches that deprecate implicit calling of
> symbolics and of polynomials? (Would they be likely to be accepted?)
Definitely for symbolics. I'm less clear about the situation for
polynomials. Regarding symbolics, I think we should definitely do
this before the Pynac switchover -- i.e., the sooner the better. That
will make the pynac switchover smoother.
William
I'm having a hard time coming up with good wording for the deprecation
message. This is what I've got so far; any suggestions for
improvements?
"Doing substitutions by calling a symbolic expression is deprecated;
use EXPR.subs(x=..., y=...) instead"
Is there a way to make it clear in this message that we're not
deprecating EXPR(x=...)? (At least I assume we're not.)
And should the recommended replacement be EXPR.subs(x=..., y=...) or
EXPR(x=..., y=...)?
Carl
Can't you put both?
"Doing substitutions by calling a symbolic expression is deprecated;
use EXPR(x=...,y=...) or EXPR.subs(x=..., y=...) instead"
Or
"Function evaluation of symbolic expressions without specifying
variables is deprecated; use EXPR(x=...,y=...), or EXPR.subs(x=...,
y=...), or explicitly give the order of variables by using f(x,y)=EXPR;
f(xvalue, yvalue)"
Jason
Hmm... if I saw one of those messages, probably my first response
would be to go look up in the documentation what the difference
between EXPR(x=..., y=...) and EXPR.subs(x=..., y=...) was, followed
by slight annoyance because I wasted my time once I discovered they
were the same. But maybe that's just because I'm strange.
That's why I'd rather not put both, anyway.
Carl
<my 2 cents>
What about
"Doing substitutions by calling a symbolic expression is deprecated;
use EXPR(x=...,y=...) or equivalently EXPR.subs(x=..., y=...) instead"
?
That way people who prefer one idiom over the other will see the one
they like, and hopefully nobody is confused into thinking they are
different.
</my 2 cents>
Cheers,
Jason Bandlow
I like the "equivalently", but EXPR(x=...) *is* calling a symbolic
expression -- both EXPR(1) and EXPR(x=1) go through the __call__
method. This is contradictory to someone who knows the Python
internals.
Nick
One more message about why I don't like mentioning both, and then I'll
shut up on that topic:
"... people who prefer one idiom over the other...": How is our
presumed beginning Sage user supposed to choose one over the other, if
we can't? Flip a coin?
Nick Alexander's point about EXPR(x=...) actually being a call is
another reason to not mention both options. That could presumably be
fixed with a wording change, but I also have a preference for not
including a multi-paragraph essay in the warning message :)
Carl
If we want short and sweet, just say: "... is deprecated: use ...".
Nick
OK, I've posted a patch that deprecates implicit calling of symbolics
(not polynomials) at
http://trac.sagemath.org/sage_trac/ticket/5413
Interested parties can look at the patch there and see how much
syntactic overhead it adds to avoid the deprecation warnings (not
much, IMHO). Also, there's one set of warnings that I didn't fix (in
piecewise.py); any suggestions on the right thing to do there would be
welcome.
Carl