@dharr

I have worked a bit with the two additional ideas that you have most recently described. I'm not sure whether I will find them helpful for the sort of work that I do. Here're my thoughts on those two.

The notion of only computing with the units of a variable that has no value in the list of equations is equivalent to stating that the value of that variable is 1. That might sometimes be what I would want perhaps, but most often I'd rather just leave that variable intact in the expression and give it a different value at some other time as needed. To leave it intact, I'll just not list it. So I don't plan to adopt that idea.

The idea of making it possible to specify units for indexed variables is interesting. I haven't usually found occasion to write expressions that involve indexed variables, but perhaps I will in future. The basic notion seems a good one, and a variant that I have considered might be even more useful. If one had the equation F = m * a and had a list m := [ 1, 2, 3 ], then one might want to evaluate for F as in evalu( F, [m=m[1],a=3] ) . That would evan enable one to turn the index [1] into [i] and loop through a list of values. This doesn't work, of cource, since the m=m[1] equation raises the error "protected". If, however, there were some way around this error that did't force a renaming to avoid the error, then that might prove useful, too. I'm keeping the basic idea described in my own code, although I'm not sure when I might have occasion to use it.

I have also made different addition to your basic notion of using Maple attributes since I posted my last version. The symbols in the sort of expressions that I deal with include symbols for constants, and constants, too, usually have units. I define all the constants in a .mpl file which I read at the outset in a worksheet, so they are always available. My convention is to denote constants with the same symbol as occurs in expressions but with a postfix underline added, e.g. G_ = 6.67e-8 * Unit(dyn*cm/g^2) is the Newton gravitational constant. Then when I want to evaluate an expression that contains the constant, I just put the equation G=G_ into the list of equations for the evalu procedure. When I do that, the value for this equation will already have units. To facilitate that approach, I have made two modifications. 1) I added a findunits procedure; 2) the evalu procedure now sends entire equations rather than just variables to findunits; 3) if the findunits procedure detects existing units in rhs(vals) it returns a 1 instead of units. Doing this lets the rhs(val) that already has units to pass through into the calculations without having any units added. These changes are in the following.

findunits := proc(val)

local var, valu:

var:=lhs(val); valu:=rhs(val);

if type(var,symbol) and type(var, `attributed`) then

return attributes(var); # var is a symbol that has attibutes, assumed to be units

elif type(var,symbol) then

if type(rhs(val), with_unit) then

return 1; # var is a symbol that has no attributes but already has units

end if:

else

if type( op(0,var), `attributed`) then

return attributes(op(0,var)); # var is not symbol but its base name is has attributes

else

return "an equation has no attributes and no units";

end if :

end if;

end proc:

evalu := proc(expr,vals::{set(equation),list(equation),equation})

if type(vals,equation) then

combine(eval(expr,lhs(vals)=rhs(vals)*findunits(vals)),units);

elif type(vals,set) or type(vals,list) then

combine(eval(expr,map(vals->lhs(vals)=rhs(vals)*findunits(vals),vals)),units);

else

return "2nd argument must be equation or list or set of equations";

end if:

end proc: