Re: Problem with Conditiond Function
- To: mathgroup at smc.vnet.net
- Subject: [mg7918] Re: Problem with Conditiond Function
- From: Dick Zacher <dick at loc3.tandem.com>
- Date: Mon, 21 Jul 1997 03:22:09 -0400
- Organization: Tandem Computers
- Sender: owner-wri-mathgroup at wolfram.com
Hans Steffani wrote: > > I have problems with the code below. > foo[ Inverse[T11], Scalars->{T11} ] > should produce 1/T11. > > This is ok but ofter foo[] is called the first time > Inverse[T11] is always evaluated to 1/T11 which is > not what I want and further calls of foo[] fail. > > What am I doing wrong? > > Hans Friedrich Steffani > > --snip--snap-- > (* I Hope that the Rule will tested every time *) > Unprotect[Inverse]; > Inverse[m_] := 1/m /; MemberQ[$theScalars,m]; > Protect[Inverse]; > > (* And this is the function which tells what are > $theScalars is *) > > foo[expr_,opt:Scalars->theScalars_List]:= > Module[{}, > > Unprotect[Inverse]; > $theScalars := theScalars; > expr = expr; > Clear[ $theScalars ]; > Protect[Inverse]; > expr > ] > > Inverse[T11] (* ok *) > foo[ Inverse[T11], Scalars->{T11} ] (* ok *) > Inverse[T11] (* why Do I get 1/T *) > foo[ Inverse[T11], Scalars->{T11} ] (* fails with error *) > > --snip--snap-- > > -- > Hans Friedrich Steffani > Institut fuer Elektrische Maschinen und Antriebe, TU Chemnitz-Zwickau > mailto:hans.steffani at e-technik.tu-chemnitz.de > http://www.tu-chemnitz.de/~hfst/ Hans, There are several interesting questions here. The first two are the ones you asked: The reason Inverse[T11] always evaluates to 1/T11 after the first call to foo is that the assignment expr = expr; is actually this: Inverse[T11] = 1/T11; That is because the symbol expr gets replaced by Inverse[T11] inside foo when it is invoked the first time. So you are redefining Inverse[T11]. That works, because at the time you make the assignment, Inverse is unprotected. The second time through foo, Inverse[T11] has already been evaluated (because of your inadvertent redefinition) to 1/T11 by the time you make the assignment expr = expr, so this time you are really trying to make this assignment: 1/T11 = 1/T11 or to put it in FullForm, Power[T11,-1] = Power[T11,-1]. However, the function Power is protected, so you can't redefine it like this. Therefore you get an error message. You can fix this by defining a local variable, say expr1, inside the Module, and making the assignment expr1 = expr; instead of expr = expr; then you return the value of expr1. That should work. However, it leads to the next question. Why do you need to unprotect the function Inverse inside the module? You are not redefining it there, once you have fixed the assignment statement. However, if you remove the Unprotect[Inverse] statement, foo stops working. Why? I'm not exactly sure why, but I think it is because expr has already been evaluated when you enter foo, so there is no apparent reason to reevaluate it after you redefine $theScalars; I think Mathematica assumes there are no side effects that would affect ordinary function evaluation. Unprotecting Inverse serves as a signal that the definition of Inverse has changed, so maybe expressions containing Inverse should be reevaluated. At least that is my theory. Maybe an expert will comment on this. If you define an additional attribute for foo, like this, SetAttributes[foo,HoldFirst] then Inverse[T11] is not evaluated when you enter foo. However, now it is evaluated when you do the assignment expr1 = expr, even if you do not unprotect the Inverse function. In this case, the definition for foo looks like this: SetAttributes[foo,HoldFirst]; foo[expr_,opt:Scalars->theScalars_List]:= Module[{expr1}, Global`$theScalars = theScalars; expr = expr; Clear[ $theScalars ]; expr1 ] I believe this works. I assume you needed the redefinition of Inverse for other reasons not involving the function foo. If you did not, there are certainly easier ways to code foo! -- ----------------------------- Dick Zacher Performance Engineering Dept., Tandem Computers zacher_dick at tandem.com phone: 408-285-5746 fax: 408-285-7079