RE: Evaluation rules and HoldRest
- To: mathgroup at smc.vnet.net
- Subject: [mg42653] RE: [mg42613] Evaluation rules and HoldRest
- From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
- Date: Sat, 19 Jul 2003 03:19:37 -0400 (EDT)
- Sender: owner-wri-mathgroup at wolfram.com
>-----Original Message----- >From: Matthias [mailto:spam at yourself.pl] To: mathgroup at smc.vnet.net >Sent: Friday, July 18, 2003 11:25 AM >To: mathgroup at smc.vnet.net >Subject: [mg42653] [mg42613] Evaluation rules and HoldRest > > >Hello, > >why is this not working as intended? > >=== >Assert[bool_, failedExpr_] := If[! bool, Evaluate[failedExpr]]; >SetAttributes[Assert, HoldRest]; >Assert[1 == 1, Print["Assertion violated!"]]; >=== > >The code above prints "Assertion violated". I know that the code behaves >correctly when replacing ":=" by "=". I'd like to understand why and would >appreciate any explanation, or pointer to relevant documentation. > >Thanks in advance, > > Matthias > executing your code: In[1]:= Assert[bool_, failedExpr_] := If[! bool, Evaluate[failedExpr]]; In[2]:= SetAttributes[Assert, HoldRest]; In[3]:= Assert[True, Print["Assertion violated!"]]; >From In[3]:= "Assertion violated!" In[4]:= Assert[False, Print["Assertion violated!"]]; >From In[4]:= "Assertion violated!" Obviously 'failedExpression' is executed anyways, but not when the argument is to be evaluated (as the Attributes are {HoldRest}), but when rhs is to be executed. In If[! bool, Evaluate[failedExpr]] you tell Mathematica to ignore the Attributes[If], {HoldRest, Protected}, and to Evaluate the failedExpr, in any case, independend from the outcome of bool -- and that's what you get. If you use Set (instead of SetDelayed) for the definition something different happens, look (and to look means: abandon the habit of closing every expression with a semicolon -- Mathematica is neither Pascal nor C -- use that only if you otherwise would have large output you have to suppress, i.e. because it takes too long to format it), so look: In[5]:= ClearAll[Assert] In[6]:= SetAttributes[Assert, HoldRest] In[7]:= Assert[bool_, failedExpr_] = If[! bool, Evaluate[failedExpr]] Out[7]= If[! bool, failedExpr] See what you have got: Evaluate disappeared! Now of course In[8]:= Assert[True, Print["Assertion violated!"]] In[9]:= Assert[False, Print["Assertion violated!"]] >From In[9]:= "Assertion violated!" However, this is not the right way to do it either, as you see here: In[10]:= bool = True Out[10]= True In[11]:= ClearAll[Assert] In[12]:= SetAttributes[Assert, HoldRest] In[13]:= Assert[bool_, failedExpr_] = If[! bool, Evaluate[failedExpr]] (* no(?) output *) In[14]:= Assert[True, Print["Assertion violated!"]] In[15]:= Assert[False, Print["Assertion violated!"]] So we just have been lucky prior. This works: In[16]:= ClearAll[Assert] In[17]:= SetAttributes[Assert, HoldRest] In[18]:= Assert[bool_, failedExpr_] := If[! bool, failedExpr] In[19]:= Assert[True, Print["Assertion violated!"]] In[20]:= Assert[False, Print["Assertion violated!"]] >From In[20]:= "Assertion violated!" Perhaps you don't need that function at all, and just use In[37]:= If[True, , Print["Assertion violated!"]] In[38]:= If[False, , Print["Assertion violated!"]] >From In[38]:= "Assertion violated!" or even better, reverse the semantics of bool to notbool and use If. -- Hartmut Wolf