There are many operations in Sage that take a function/expression as
the first argument, and one or more variables with ranges as
subsequent arguments.  The prototype is plot(x^2*sin(x),-4*pi,4*pi).
It would be nice if the syntax were consistent across all such
functions.  There are already tickets out asking for fixes to a few
specific cases, but it seems like it might take forever to do these
piecemeal, so I decided to make a table showing which syntax works and
which doesn't for most of the functions I could think of.

In general, I think almost all of these cases should work.  Or if some
of them shouldn't, there ought to be a clear rule (like, one sentence)
letting users know what will work and what won't.

One thing I'm not so sure about is postfix syntax.  For example,
(x^2*sin(x)).plot(-4*pi,4*pi) works, but (x^2*sin(x)).polar_plot(-4*pi,
4*pi) fails.  Is this postfix syntax nice to use?  If so, should it
work for all of these functions?  Or is it just an implementation
thing--in which case, maybe all the postfixes should become like
_plot_, and mention of them should be taken out of basic
documentation.

As an aside, in researching this issue I noticed that some parts of
the Sage implementation are fairly littered with isinstance() calls.
I think this is at least sometimes the reason that lists work and
tuples fail, or vice versa.  You could make extra sure to always say
isinstance(foo,(list,tuple)), but it's cleaner to duck type, right?
In other words, just index the thing, and catch exceptions if
necessary.  I guess it's silly to be a purist, but it does seem like a
good philosophy to keep in mind.

Maybe it would be worthwhile to abstract the argument processing for
functions of this form into a helper function somewhere so that it is
not written in a new, inconsistent way for every new function with a
variable and range.

So here's the data.  Best viewed in a fixed width font (sorry...)

One Range
---------

key
---

p: Produces a result
f: fails

symbolic:               se1 = x^2*sin(x)
callable symbolic:  cse1(x) = x^2*sin(x)
lambda function:        le1 = lambda x: x^2*sin(x)

1: fun(expr, x, -4*pi, 4*pi)
2: fun(expr, -4*pi, 4*pi)
3: fun(expr, (x, -4*pi, 4*pi))
4: fun(expr, (-4*pi,4*pi))
5: fun(expr, [x,-4*pi,4*pi])
6: fun(expr, [-4*pi,4*pi])

pre:  fun(expr,*args)
post: expr.fun(*args)

plot:                      1  2  3  4  5  6
symbolic          pre      p  p  p  p  p  p
symbolic          post     p  p  p  p  p  p
callable symbolic pre      p  p  p  p  p  p
callable symbolic post     p  p  p  p  p  p
lambda function   pre      f  p  p  p  f
p
*postfix form never works for lambda functions

polar_plot:                1  2  3  4  5
6
symbolic          pre      f  p  f  f  f  p
symbolic          post     f  f  f  f  f  f
callable symbolic pre      f  p  f  f  f  p
callable symbolic post     f  f  f  f  f  f
lambda function   pre      f  p  f  f  f
p

integral_numerical:        1  2  3  4  5
6
symbolic          pre      f  p  f  p  f  p
symbolic          post     f  f  f  f  f  f
callable symbolic pre      f  p  f  p  f  p
callable symbolic post     f  f  f  f  f  f
lambda function   pre      f  p  f  p  f  p

find_root:                 1  2  3  4  5
6
symbolic          pre      f  p  f  f  f  p
symbolic          post     f  p  f  f  f  p
callable symbolic pre      f  p  f  f  f  p
callable symbolic post     f  p  f  f  f  p
lambda function   pre      f  p  f  f  f  p

find_minimum_on_interval:  1  2  3  4  5
6
symbolic          pre      f  p  f  f  f  p
symbolic          post     f  p  f  f  f  p
callable symbolic pre      f  p  f  f  f  p
callable symbolic post     f  p  f  f  f  p
lambda function   pre      f  p  f  f  f  p

integral:                  1  2  3  4  5
6
symbolic          pre      p  f  f  f  p  f
symbolic          post     p  f  f  f  p  f
callable symbolic pre      p  f  f  f  p  f
callable symbolic post     p  f  f  f  p  f
lambda function   pre      f  f  f  f  f  f

Two Ranges
----------

key
---

p: Produces a result
f: fails

symbolic:                se2 = sin(sin(x) + y^2)
callable symbolic: cse2(x,y) = sin(sin(x) + y^2)
lambda function:        le2  = lambda x, y: sin(sin(x) + y^2)

1: fun(expr, (x, pi, pi), (y, -pi, pi))
2: fun(expr, (-pi, pi), (-pi, pi))
3: fun(expr, [x, -pi, pi],[y, -pi, pi])
4: fun(expr, [-pi, pi], [-pi, pi])

pre:  fun(expr,*args)
post: expr.fun(*args)

plot3d:                    1  2  3  4
symbolic          pre      p  p  p  p
symbolic          post     f  f  f  f
callable symbolic pre      p  p  p  p
callable symbolic post     f  f  f  f
lambda function   pre      p  p  p  p

contour_plot
symbolic          pre      p  p  p  p
symbolic          post     f  f  f  f
callable symbolic pre      p  p  p  p
callable symbolic post     f  f  f  f
lambda function   pre      p  p  p  p

integral_numerical:
symbolic          pre      f  p  f  p
symbolic          post     f  f  f  f
callable symbolic pre      f  p  f  p
callable symbolic post     f  f  f  f
lambda function   pre      f  f  f  f

integral:
symbolic          pre      f  f  f  f
symbolic          post     f  f  f  f
callable symbolic pre      f  f  f  f
callable symbolic post     f  f  f  f
lambda function   pre      f  f  f  f

It's probably also worth checking parametric_plot, parametric_plot3d,
and plot_vector_field, and I'm sure several others, but for now I'm
out of the patience for it.

integral is a special case since you can do a definite integral, as
here, or an indefinite integral.  There's also a desire to make the
syntax for integral consistent with that for derivative, but it seems
impossible to allow everything and be unambiguous.  See
http://trac.sagemath.org/sage_trac/ticket/2787

Here's the code I used to do these tests.

def prefix(funname,expr,*range):
    try:
        sage_eval(funname)(expr,*range)
        return 'p'
    except Exception, inst:
        return 'f'

def postfix(funname,expr,*range):
    try:
        getattr(expr, funname).__call__(*range)
        return 'p'
    except Exception, inst:
        return 'f'

# One Range
se1 = x^2*sin(x)
cse1(x) = x^2*sin(x)
le1 = lambda x: x^2*sin(x)
range_specs = ((x,-4*pi,4*pi),(-4*pi,4*pi),((x,-4*pi,4*pi),),((-4*pi,
4*pi),),([x,-4*pi,4*pi]),([-4*pi,4*pi]))
funnames =
('plot','polar_plot','integral_numerical','find_root','find_minimum_on_interval','integral')
# there is integrate, but no integrate_numerically
expressions = (se1,cse1,le1)
syntaxes = (prefix,postfix)
[[syntax(funname,expr,*range) for range in range_specs] for funname in
funnames for expr in expressions for syntax in syntaxes]

# Two Ranges
var('x,y')
se2 = sin(sin(x) + y^2)
cse2(x,y) = sin(sin(x) + y^2)
le2  = lambda x, y: sin(sin(x) + y^2)
range_specs = (((x,-pi,pi),(y,-pi,pi)),((-pi,pi),(-pi,pi)),([x,-pi,pi],
[y,-pi,pi]),([-pi,pi],[-pi,pi]))
funnames = ('plot3d','contour_plot','integral_numerical','integral')
expressions = (se2,cse2,le2)
syntaxes = (prefix,postfix)
[[syntax(funname,expr,*range) for range in range_specs] for funname in
funnames for expr in expressions for syntax in syntaxes]

Yours in Sage,

JM

--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---

Reply via email to