subs deprecation -- what the heck?!

1,597 views
Skip to first unread message

William Stein

unread,
Feb 29, 2016, 5:56:06 PM2/29/16
to sage-devel
Hi,

Somebody doing differential equations sent me this code, which you can
run in a fresh sage-6.9 session:

var('x,y')
y = function('y')(x)
eqn = diff(x^2+y^2==25,x)
sol0 = solve(eqn, diff(y,x))
sol1 = sol0[0].subs({x:3})
sol1.subs({y(3):4})

The *last line* outputs:

D[0](y)(3) == (-3/4)
DeprecationWarning: Substitution using function-call syntax and
unnamed arguments is deprecated and will be removed from a future
release of Sage; you can use named arguments instead, like EXPR(x=...,
y=...)
See http://trac.sagemath.org/5930 for details.
exec compile(block+'\n', '', 'single') in namespace, locals

I have some problems with this:

(1) trac #5930 hasn't been touched in *7 years*, and doesn't mention
subs anywhere. Maybe referencing 5930 was a typo?

(2) The actual substitution above is *NOT* function-call syntax --
it's passing in a dictionary, which seems like a very reasonable way
to do substitution in general and should never get deprecated. So why
is that deprecation warning appearing? Is it actually coming from
some other code inside the library?

(3) The suggestion to "use named arguments instead, like EXPR(x=...,
y=...)" seems confusing to me, since it's impossible to specify y(3)
as a named argument. Also, it assumes that a variable is the same as
its string, which is a bad assumption to make and just begs for bugs;
using a dictionary (or ==) is always safer and should be preferred,
right?

William

John H Palmieri

unread,
Feb 29, 2016, 6:11:26 PM2/29/16
to sage-devel
On Monday, February 29, 2016 at 2:56:06 PM UTC-8, William wrote:
Hi,

Somebody doing differential equations sent me this code, which you can
run in a fresh sage-6.9 session:

var('x,y')
y    = function('y')(x)
eqn  = diff(x^2+y^2==25,x)
sol0 = solve(eqn, diff(y,x))
sol1 = sol0[0].subs({x:3})
sol1.subs({y(3):4})

The *last line* outputs:

D[0](y)(3) == (-3/4)
DeprecationWarning: Substitution using function-call syntax and
unnamed arguments is deprecated and will be removed from a future
release of Sage; you can use named arguments instead, like EXPR(x=...,
y=...)
See http://trac.sagemath.org/5930 for details.
  exec compile(block+'\n', '', 'single') in namespace, locals

I have some problems with this:

 (1) trac #5930 hasn't been touched in *7 years*, and doesn't mention
subs anywhere.  Maybe referencing 5930 was a typo?

The patch mentions subs. I'm not an expert in this, but I think it's the right ticket.
 
 (2) The actual substitution above is *NOT* function-call syntax --
it's passing in a dictionary, which seems like a very reasonable way
to do substitution in general and should never get deprecated.  So why
is that deprecation warning appearing?  Is it actually coming from
some other code inside the library?

Regarding points (2) and (3), the warning comes from the "y(3)" part of the line, not the "subs" part of the line. I think if you replace the last line with "sol1.subs({y.subs(x=3):4})", no warning.
 

Andrzej Giniewicz

unread,
Feb 29, 2016, 6:12:02 PM2/29/16
to sage-devel
Hi,

isn't this comming from y(3)? Using either

sol1.subs({y(x=3):4})

or

y(x) = function('y')(x)

makes the warning disappear. Nonetheless I also got lot of questions
from students about this warning.

Regards,
Andrzej.
> --
> You received this message because you are subscribed to the Google Groups "sage-devel" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+...@googlegroups.com.
> To post to this group, send email to sage-...@googlegroups.com.
> Visit this group at https://groups.google.com/group/sage-devel.
> For more options, visit https://groups.google.com/d/optout.

William Stein

unread,
Feb 29, 2016, 6:34:55 PM2/29/16
to sage-devel
Thanks to Andrzej and John for the clarification. I thought a lot
about this before emailing sage-devel, yet still didn't realize it was
"y(3)" that caused the problem. Thanks for the help.

On Mon, Feb 29, 2016 at 3:11 PM, John H Palmieri <jhpalm...@gmail.com> wrote:
>> (1) trac #5930 hasn't been touched in *7 years*, and doesn't mention
>> subs anywhere. Maybe referencing 5930 was a typo?
>
> The patch mentions subs. I'm not an expert in this, but I think it's the
> right ticket.

So we deprecated this 7 years ago? Yikes. Also, that patch is 1.2MB,
so it probably mentions everything.

Maybe we should finally really deprecate this, or de-deprecate it, if
we're never going to.


--
William (http://wstein.org)

Michael Orlitzky

unread,
Mar 1, 2016, 8:09:41 AM3/1/16
to sage-...@googlegroups.com
On 02/29/2016 06:34 PM, William Stein wrote:
>
> So we deprecated this 7 years ago? Yikes. Also, that patch is 1.2MB,
> so it probably mentions everything.
>
> Maybe we should finally really deprecate this, or de-deprecate it, if
> we're never going to.

You can't get rid of it because piecewise functions will stop working:

http://trac.sagemath.org/ticket/12070

William Stein

unread,
Mar 1, 2016, 8:26:29 AM3/1/16
to sage-devel
Let's suppose somebody (I think me in this case?) decides to deprecate
something... and never does after 7 years. And there is a big warning
message that many new users see. Maybe we shouldn't deprecate it at
all. For what it is worth, I would be fine with simply *not*
deprecating function call syntax, i.e., get rid of this:
"DeprecationWarning: Substitution using function-call syntax and
unnamed arguments is deprecated and will be removed from a future
release of Sage; you can use named arguments instead..."

William

Jeroen Demeyer

unread,
Mar 1, 2016, 11:09:56 AM3/1/16
to sage-...@googlegroups.com
On 2016-03-01 14:25, William Stein wrote:
> And there is a big warning message that many new users see.

For good reasons, since using function-call syntax will bite you sooner
or later. I think it's best to allow the syntax while keeping the warning.

William Stein

unread,
Mar 1, 2016, 11:15:56 AM3/1/16
to sage-...@googlegroups.com
-1 to telling users that a syntax is deprecated and will be removed, but planning to never remove it. 


 

--
You received this message because you are subscribed to the Google Groups "sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+...@googlegroups.com.
To post to this group, send email to sage-...@googlegroups.com.
Visit this group at https://groups.google.com/group/sage-devel.
For more options, visit https://groups.google.com/d/optout.


--
Sent from my massive iPhone 6 plus.

Nils Bruin

unread,
Mar 1, 2016, 11:43:40 AM3/1/16
to sage-devel
On Tuesday, March 1, 2016 at 8:15:56 AM UTC-8, William wrote:
-1 to telling users that a syntax is deprecated and will be removed, but planning to never remove it. 

+1 to executing the removal.

We can't let a lottery like this:

sage: var('foo,bar')
(foo, bar)
sage: f=foo+bar
sage: f(1)
foo + 1

go silently. The proper solution is raising an error.

We *could* special case the situation where len(f.variables()) == 1 and one argument is given. Apart from no arguments at all, That's the only situation that's unambiguous, as far as I know.

The problem at http://trac.sagemath.org/ticket/12070 is just misuse, so should be resolved by improving documentation.

David Roe

unread,
Mar 1, 2016, 12:36:51 PM3/1/16
to sage-devel
On Tue, Mar 1, 2016 at 11:43 AM, Nils Bruin <nbr...@sfu.ca> wrote:
On Tuesday, March 1, 2016 at 8:15:56 AM UTC-8, William wrote:
-1 to telling users that a syntax is deprecated and will be removed, but planning to never remove it. 

+1 to executing the removal.

We can't let a lottery like this:

sage: var('foo,bar')
(foo, bar)
sage: f=foo+bar
sage: f(1)
foo + 1

go silently. The proper solution is raising an error.

We *could* special case the situation where len(f.variables()) == 1 and one argument is given. Apart from no arguments at all, That's the only situation that's unambiguous, as far as I know.

+1 to finishing the deprecation and adding a special case for one variable.  We should make sure that the error message is helpful.
David
 
The problem at http://trac.sagemath.org/ticket/12070 is just misuse, so should be resolved by improving documentation.

--

Travis Scrimshaw

unread,
Mar 1, 2016, 6:21:35 PM3/1/16
to sage-devel, roed...@gmail.com
+1 to removing the deprecation and special casing the 1 variable (if it is easy enough to implement).

Best,
Travis

kcrisman

unread,
Mar 1, 2016, 8:23:36 PM3/1/16
to sage-devel


On Tuesday, March 1, 2016 at 6:21:35 PM UTC-5, Travis Scrimshaw wrote:
+1 to removing the deprecation and special casing the 1 variable (if it is easy enough to implement).



If I recall correctly, Jason Grout's example for this is 

x+y-y

which becomes x but in principle had two variables, so how do you know which one is "right"?

That said, this has been around a long time so it is definitely long beyond the deprecation period and one would be more than justified in removing it, with or without the one-var version.

Nils Bruin

unread,
Mar 2, 2016, 11:45:19 AM3/2/16
to sage-devel
On Tuesday, March 1, 2016 at 5:23:36 PM UTC-8, kcrisman wrote:
If I recall correctly, Jason Grout's example for this is 

x+y-y

which becomes x but in principle had two variables, so how do you know which one is "right"?

Hm, I'm not sure that's a problem here. Indeed if both are defined then one would hope that

f1(a)+f2(a)+f3(a) = (f1+f2+f3)(a)

which is still OK in your example. If one of them errors out then there's not a direct problem.

Anyway, I'm -1 on supporting calling expressions with one variable (and one argument) and/or supporting calling expressions with an empty argument list (which would also be unambiguous) and/or calling constant expressions with no arguments at all.

It's easy to explain "expressions do not support calling syntax. You need a function for that".
It's hard to explain "expressions don't really support calling, except in some edge cases that you will initially encounter most".
By having the muddling exceptions, you make it harder for novice users to start learning the difference between a symbolic expression and a symbolic function; a difference they'll need later anyway.
If you don't want to talk about functions at all, just use "subs".

William Stein

unread,
Mar 2, 2016, 12:04:58 PM3/2/16
to sage-devel
You're right. Plus we just spent 7+ years telling everybody that the
above is what we are going to do. So let's do it.

William

> --
> You received this message because you are subscribed to the Google Groups
> "sage-devel" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sage-devel+...@googlegroups.com.
> To post to this group, send email to sage-...@googlegroups.com.
> Visit this group at https://groups.google.com/group/sage-devel.
> For more options, visit https://groups.google.com/d/optout.



--
William (http://wstein.org)

Michael Orlitzky

unread,
Mar 4, 2016, 1:52:58 PM3/4/16
to sage-...@googlegroups.com
On 03/02/2016 11:45 AM, Nils Bruin wrote:
>
> It's easy to explain "expressions do not support calling syntax. You
> need a function for that".
> It's hard to explain "expressions don't really support calling, except
> in some edge cases that you will initially encounter most".
> By having the muddling exceptions, you make it harder for novice users
> to start learning the difference between a symbolic expression and a
> symbolic function; a difference they'll need later anyway.
> If you don't want to talk about functions at all, just use "subs".
>

I went back and looked at all of the piecewise code I wrote during that
era. I was able to fix it all to avoid the DeprecationWarnings (thanks).

But, proposing that we get rid of symbolic expressions in piecewise
functions is stronger than the proposal to get rid of unnamed arguments.
This works, and accounts for just about every use of piecewise() you'll
find, even the ones in the Sage library:

sage: f = piecewise([[(-1,1),x]])
sage: f.plot()

The proposal would require,

sage: f = piecewise([[(-1,1), x.function(x)]])

which is a little weird and not used anywhere that I've seen. Some other
odd cases that I ran into were,

f = cos(x).function(x)

and of course the constants,

f = SR(1).function(x)

But overall I agree that forcing piecewise() to take functions creates a
better mental model. It just may be harder to get rid of than the
unnamed-argument function call syntax alone.

Nils Bruin

unread,
Mar 4, 2016, 3:39:41 PM3/4/16
to sage-devel
On Friday, March 4, 2016 at 10:52:58 AM UTC-8, Michael Orlitzky wrote:
But, proposing that we get rid of symbolic expressions in piecewise
functions is stronger than the proposal to get rid of unnamed arguments.
This works, and accounts for just about every use of piecewise() you'll
find, even the ones in the Sage library:

  sage: f = piecewise([[(-1,1),x]])
  sage: f.plot()

The proposal would require,

  sage: f = piecewise([[(-1,1), x.function(x)]])

which is a little weird and not used anywhere that I've seen.

I think it suggests the proper solution is having one of two things:

 - piecewise expressions, where we'd need to specify to which variable the condition (belonging to an interval) applies. That basically means we'd need to be able to pass expressions involving conditionals (perhaps only a limited kind) through the symbolic machinery.
 - a way of specifying a piecewise function *using expressions*, i.e., something along the lines of

piecewise([[(-1,1),x],[(1,2),x^2]],arguments=(x,))

as a replacement for

piecewise([[(-1,1),x.function(x)],[(1,2),(x^2).function(x)]])

note that the present situation allows for

piecewise([[(-1,1),x],[(1,2),y^2])

which I think is worth getting rid of. There needs to be some indication somewhere in what way the interval relates to the variables in the expression.

Some other
odd cases that I ran into were,

  f = cos(x).function(x)

f = cos

would do.

  f = SR(1).function(x)

That only looks funny because of the method notation. If you write this in a functional way:

f = symbolic_function(x,1)

it's not nearly as weird. (It's basically "lambda x: 1" which is a perfectly fine way of defining a constant function).

It would be nice to use "function" for this, but that's unfortunately a namespace clash.

But overall I agree that forcing piecewise() to take functions creates a
better mental model. It just may be harder to get rid of than the
unnamed-argument function call syntax alone.

I think something along the lines of

piecewise(x, [[(-1,1),x],[(1,2),x^2]])

might be a better compromise then. On the other hand, having

piecewise([[(-1,1),sin],[(1,2),cos]])

 makes perfect sense too, so one would have to think carefully about the best calling interface to allow for both.

Ralf Stephan

unread,
Mar 19, 2016, 10:24:22 AM3/19/16
to sage-devel
Coming late to this...


On Friday, March 4, 2016 at 9:39:41 PM UTC+1, Nils Bruin wrote:
 - a way of specifying a piecewise function *using expressions*, i.e., something along the lines of

piecewise([[(-1,1),x],[(1,2),x^2]],arguments=(x,))

This is implemented in the current #14801 branch with the keyword var.
 
as a replacement for

piecewise([[(-1,1),x.function(x)],[(1,2),(x^2).function(x)]])

note that the present situation allows for

piecewise([[(-1,1),x],[(1,2),y^2])

which I think is worth getting rid of.

This behaves now different in #14801:

sage: piecewise([[(-1,1),x],[(1,2),y^2]])
piecewise
(x|-->x on (-1, 1), x|-->y^2 on (1, 2); x)
 
There needs to be some indication somewhere in what way the interval relates to the variables in the expression.
 ...

Regards,
Reply all
Reply to author
Forward
0 new messages