On 5/7/06, Robert Dodier <robert.dodier at gmail.com> wrote:
>
> At present the functions op and args barf on atoms.
> I propose that op and args return false when the argument is an atom.
>
> This change is intended to obviate the need to always test whether
> the argument is an atom before calling op or args.
This does indeed make one use-case easier, namely a dispatch of the form:
block( [op: op(expr)],
if op=false then... // 3, 3.0, 3.0b0, x
// but NOT 1/3, %pi/2,
x[1]
elseif op="+" then ...
...)
However, it also makes it much easier to incorrectly assume that an
expression *has* an operator when it doesn't, and to propagate nonsense
further into the program. Errors are a *good* thing in cases like this.
For that matter, checking whether an expression is an atom is usually not
the right thing -- you want to check whether it is a symbolic constant or
variable, which may be subscripted, so the above code would become:
block( [op],
if mapatom(expr) then ... // 3, 3.0, 3.0b0, 1/3, %pi, x,
x[1]
elseif (op:op(expr))="+" then ...
...)
or in more sophisticated code, probably something like
block( [op],
if numberp(expr) then ... // 3, 3.0, 3.0b0, 1/3
elseif constantp(expr) then ... // %pi, %pi/2
elseif mapatom(expr) then ... // x, x[1]
...)
Alternatively, if you only want to handle a few operators, it might be
cleaner to define:
plusexprp(expr):= not(atom(expr)) and op(expr)="+"
and use those. Yes, there is a slight performance penalty....
The main ugly thing in all this is the name "mapatom" (meaning something
that 'map' treats as atomic).
Oh, and by the way, it is probably a bad idea to use "op" in code in the
first place, since its behavior is controlled by the global inpart flag.
Much better to define inop(ex):=block([inflag:true],op(ex)), which is both
more consistent and much more efficient. By the way, did you know that
op(3/4)=inop(3/4)="//"? Surprise! If we were designing from scratch, I
would *not* have op(x[1])=x or op(3/4)=/, but I think those are important
cases to keep backwards-compatible.
In all, it seems to me that it would be a classic design error to have op do
anything other than give an error when it is passed inappropriate arguments=
.
-s