Mathematica 9 is now available
Services & Resources / Wolfram Forums
-----
 /
MathGroup Archive
1997
*January
*February
*March
*April
*May
*June
*July
*August
*September
*October
*November
*Archive Index
*Ask about this page
*Print this page
*Give us feedback
*Sign up for the Wolfram Insider

MathGroup Archive 1997

[Date Index] [Thread Index] [Author Index]

Search the Archive

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


  • Prev by Date: Speeding up calculations by lowering the precision ?
  • Next by Date: Re: More on Positive[x]
  • Previous by thread: Problem with Conditiond Function
  • Next by thread: Re: multi-dim integration