MathGroup Archive 2001

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

Search the Archive

RE: Re: exchanging 2 elements in a list (problem with Block)

  • To: mathgroup at smc.vnet.net
  • Subject: [mg27655] RE: [mg27631] Re: exchanging 2 elements in a list (problem with Block)
  • From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.de>
  • Date: Sat, 10 Mar 2001 00:49:44 -0500 (EST)
  • Sender: owner-wri-mathgroup at wolfram.com

Dear Allan,

you'r right, a general problem with, not of, Block. Block indeed does exacly
what it is supposed to do. To prototype it:

In[10]:= blockbuster[m_] := Block[{s = m}, s]
In[11]:= blockbuster[{a, s}]; 
>From In[11]:=
$RecursionLimit::reclim:Recursion depth of 256 exceeded.


This is but the consequence of dynamical scoping of symbols ("variables")
introduced with Block. It occurs when bringing an unevaluated symbol into
the scope of Block where that is being redefined. The semantics of Block
require, when evaluating, to use the redefined value of the symbol. Such
this effectively is the same as in

In[12]:= s = {a, s}
>From In[12]:=
$RecursionLimit::reclim:Recursion depth of 256 exceeded.

which certainly is not surprising.

This kind of problems is shared e.g. by all early Lisp dialects having been
discussed extensively, and being the reason for generally converting to
lexical scoping. That it is present at all in Mathematica presumably has
historical reasons. However it also has certain advantages, and I'm happy to
have it at my disposal. We have to be wary however, and routinely better use
Module. So a first thought when seeing a Block might be: "will it work with
Module?"

A method to make Block work with Swap1 (not seriously meant for this case)
is to restrict evaluation to where it is needed:

 
In[18]:= Clear[s]
In[19]:= lazySwap[m_,i_,j_] := 
           Evaluate /@ Block[{s = Unevaluated /@ m}, 
                              s[[{i, j}]] = s[[{j, i}]];
                              s]

In[20]:= lazySwap[{a, s},1,2]
Out[20]= {s,a}


Finally a note I would like to add to Richard's problem (after all has been
said by you and Jens-Peer Kuska, to mention). His pitfall is common to all
having been absent from Mathematica for a while, and extensively programming
in C or a similiar language, then misconstruing a definition in Mathemtica
for a "function procedure". A definition is a term rewrite rule, and there
is no such thing as a "formal parameter" (with the meaning of a storage
location behind).
Pure lambda calculus wouldn't rise the idea, and Mathematica comes closer to
that than to C.

How to approach call by reference semantics has been shown by Jens-Peer and
David B. Wagner in his Book "Power Programming with Mathematica, the Kernel"

http://www.amazon.com/exec/obidos/ASIN/007912237X
devotes all of §4.4 "Parameter-Passing Semantics" (of chapter 4 "Procedural
Programming") to the theme.

With kind regards, yours
Hartmut




> -----Original Message-----
> From:	Allan Hayes [SMTP:hay at haystack.demon.co.uk]
To: mathgroup at smc.vnet.net
> Sent:	Friday, March 09, 2001 8:36 AM
> To:	mathgroup at smc.vnet.net
> Subject:	[mg27631] Re: exchanging 2 elements in a list  (problem with
> Block)
> 
> Richard Fateman has pointed a bug out to me in my previous posting --
> 
> Block in
> 
> Swap1[m_,i_,j_]:=
>  Block[{s=m},
>      s[[{i,j}]]= s[[{j,i}]];s
>     ]
> 
> causes
> 
> Swap1[{a,s},1,2];
> 
> $RecursionLimit::reclim: Recursion depth of 256 exceeded.
> 
> Replacing Block with Module corrects this.
> 
> *** However this example does point up a general problem with Block ***
> 
> 
> --
> Allan
> ---------------------
> Allan Hayes
> Mathematica Training and Consulting
> Leicester UK
> www.haystack.demon.co.uk
> hay at haystack.demon.co.uk
> Voice: +44 (0)116 271 4198
> Fax: +44 (0)870 164 0565
> 
> "Allan Hayes" <hay at haystack.demon.co.uk> wrote in message
> news:98722r$8rs at smc.vnet.net...
> >
> > Richard Fateman
> >
> > Richard,
> > Two ways:
> >
> > Swap1[m_,i_,j_]:=
> >   Block[{s=m},
> >     s[[{i,j}]]= s[[{j,i}]];s
> >     ]
> >
> > Swap1[{a,b,c,d,e,f},2,4]
> >
> > {a,d,c,b,e,f}
> >
> > Swap2[m_,i_,j_]:=
> >   ReplacePart[m,m,{{i},{j}},{{j},{i}}]
> >
> > Swap2[{a,b,c,d,e,f},2,4]
> >
> > {a,d,c,b,e,f}
> >
> > For swapping columns we have (besides double Transpose versions of the
> > above):
> >
> > m= {{a,b,c,d},{e,f,g,h}};
> >
> > m[[All,{2,4}]]= m[[All,{4,2}]];m
> >
> > {{a,d,c,b},{e,h,g,f}}
> >
> > Next, I look at the first three of  your examples.
> >
> > 1 ---------------------------------------------------------------------
> >
> > Clear["`*"]
> >
> > Exchangeitems1[m_, r_Integer, s_Integer] :=
> >    Block[{temp = m[[r]]},
> >      m[[r]] = m[[s]];
> >      m[[s]] = temp;
> >      m
> >
> >    ];
> >
> > Exchangeitems1[{a,b,c,d,e,f},2,4]
> >
> >         Set::setps:{a,b,c,d,e,f} in assignment of part is not a symbol.
> >
> >         Set::setps:{a,b,c,d,e,f} in assignment of part is not a symbol.
> >
> >         {a, b, c, d, e, f}
> >
> >
> > Analysis
> >
> > Crucial here is that {a,b,c,d,e,f} is passed directly to m, so we get,
> for
> > example
> >   {a,b,c,d,e,f} [[r]]={a,b,c,d,e,f} [[s]]
> >
> > However settings like
> >
> > mm[[3]] = p
> >
> > works only when mm is a *symbol* that has been assigned a value by Set,
> not
> > SetDelayed. For example
> >
> > mm= Evaluate[{1,2,3,4}];
> >
> > and, of course this value must have a position with index 3.
> >
> > Further, when these conditions hold, it is the stored value of  mm that
> is
> > changed: a new mm is not constructed -- this more efficient.
> >
> > 2 --------------------------------------------------------
> >
> > Clear["`*"]
> >
> > Exchangeitems2[m_,r_Integer,s_Integer]:=
> > Block[{temp},
> >       temp=m[[r]];
> >       m=ReplacePart[m,m[[s]],{r}];
> >       m=ReplacePart[m,temp,{s}];
> >       m
> > ];
> >
> > Exchangeitems2[{a,b,c,d,e,f},2,4]
> >
> >         {a,d,c,d,e,f}
> >
> >
> > Analysis:
> >
> > The replacement of m by {a,b,c,d,e,f} is a crucial here also:
> > First we get
> >
> > temp = {a,b,c,d,e,f}[[2]]
> >
> > that becomes
> >
> >         temp = b, which is stored  (actually as a replacement rule)
> >
> >
> > Then we get
> >
> > {a,b,c,d,e,f}= ReplacePart[{a,b,c,d,e,f},{a,b,c,d,e,f}[[4]],{2}]
> >
> > that becomes
> >
> >         {a,b,c,d,e,f}= {a,d,c,d,e,f}
> >
> > This results in the following  being stored
> >    a=a, b=d, c=c, d=d, e=e, f =f .
> > Here
> >    b=d
> > is the important one if course.
> > So, when the next line is evaluted we begin with
> >
> >         {a,b,c,d,e,f}= ReplacePart[{a,b,c,d,e,f},temp,{2}]
> >
> > Which becomes successively (temp has already been defined as b, *and
> > a,b....on  the left side are not evaluated*)
> >
> >         {a,b,c,d,e,f}= ReplacePart[{a,d,c,d,e,f},temp,{2}]
> >         {a,b,c,d,e,f}= ReplacePart[{a,d,c,d,e,f},b,{2}]
> >         {a,b,c,d,e,f}= ReplacePart[{a,d,c,d,e,f},d,{2}]
> >         {a,b,c,d,e,f}= {a,d,c,d,e,f}
> >
> > This does not change the rules stored.
> >
> > Finally we evaluated {a,b,c,d,e,f} with  b =d in store.
> > This gives
> >             {a,d,c,d,e,f}
> >
> > ** And  b = d is still around
> >
> > b
> >
> >         d
> >
> > **Actually, worse could happen
> >
> > Exchangeitems2[{1,2,3,4,5,6},2,4]
> >
> >         Set::setraw: Cannot assign to raw object 1.
> >
> >         Set::setraw: Cannot assign to raw object 2.
> >
> >         Set::setraw: Cannot assign to raw object 3.
> >
> >         General::stop: Further output of Set::setraw will be suppressed
> > during this \
> >         calculation.
> >
> > {1,2,3,4,5,6}
> >
> > 3 -------------------------------------------------------------
> >
> > I have interchanged k and m in the following to conform to the previous
> two
> > definitions
> >
> > Clear["`*"]
> > Exchangeitems[m_,r_Integer,s_Integer]:=Block[{k,temp},k=m;
> >       temp=k[[r]];
> >       k=ReplacePart[k,k[[s]],{r}];
> >       k=ReplacePart[k,temp,{s}];
> >       k];
> >
> > Exchangeitems[{a,b,c,d,e,f},2,4]
> >
> >         {a,d,c,b,e,f}
> >
> > Analysis
> >
> > The variable k is not useless, it is what makes this work.
> > We get
> >  k = {a,b,c,d,e,f} , which is stored
> >  temp = b is stored
> > Then, the symbol k is redefined by
> >  k = ReplacePart[{a,b,c,d,e,f} ,{a,b,c,d,e,f} [[4]],{2}]
> > which becomes
> >  k = {a,d,c,d,e,f}, which is stored
> > Then
> >  k=ReplacePart[{a,d,c,d,e,f},b,{4}]
> > which becomes
> >  k={a,d,c,b,e,f}, which is stored
> > Finally k evauates to {a,d,c,b,e,f}
> >
> > --
> > Allan
> > ---------------------
> > Allan Hayes
> > Mathematica Training and Consulting
> > Leicester UK
> > www.haystack.demon.co.uk
> > hay at haystack.demon.co.uk
> > Voice: +44 (0)116 271 4198
> > Fax: +44 (0)870 164 0565
> >
> > "Richard Fateman" <fateman at cs.berkeley.edu> wrote in message
> > news:98505m$5h0 at smc.vnet.net...
> > >
> > > Actually, I wanted to exchange 2 rows in a matrix,
> > > but writing this program I found I could not even
> > > exchange 2 elements in a simple list by the first
> > > two (most obvious) programs I wrote.  The third
> > > works. So does the fourth.
> > >
> > > Anyone care to explain why the first 2 fail?
> > > (Typing them in to a system does not really explain
> > > that much.)
> > >
> > > try Exchangitems[{a,b,c,d,e,f},2,4] which should
> > > result in {a,d,c,b,e,f}.
> > > Naturally it should not SET any of the variables
> > > a,b,c,... . version 2 sets b to the value d.
> > >
> > >
> > > Exchangeitems1[m_,r_Integer,s_Integer]:=
> > > Block[{temp=m[[r]]},
> > >        m[[r]]=m[[s]];
> > >        m[[s]]=temp;
> > >        m];
> > >
> > >
> > > Exchangeitems2[m_,r_Integer,s_Integer]:=
> > > Block[{temp},
> > >        temp=m[[r]];
> > >        m=ReplacePart[m,m[[s]],{r}];
> > >        m=ReplacePart[m,temp,{s}];
> > >        m];
> > >
> > >
> > > (* this works by adding a useless variable *)
> > > Exchangeitems[k_,r_Integer,s_Integer]:=
> > > Block[{m,temp},
> > >        m=k;
> > >        temp=m[[r]];
> > >        m=ReplacePart[m,m[[s]],{r}];
> > >        m=ReplacePart[m,temp,{s}];
> > >        m];
> > >
> > > (*Here is a more "functional" version *)
> > >
> > > ei[k_, low_, hi_]:= ei[k,hi,low] /; low>hi;
> > > ei[k_, low_, hi_]:= k /; low==hi;
> > > ei[k_, low_, hi_] :=
> > >   Flatten[{Take[k, {1, low - 1}], {k[[hi]]},
> > >       Take[k, {low + 1, hi - 1}], {k[[low]]}, Drop[k, hi]}, 1];
> > >
> > > (*and here is an APL-style version*)
> > >
> > >
> > > ei2[k_,r_,s_]:=Table[Switch[j,r,k[[s]],
> > >                               s,k[[r]],
> > >                               _,k[[j]]],
> > >                    {j,1,Length[k]}];
> > >
> > >
> > >
> > > Is there a nice, efficient, (and correct) program to do this?
> > >
> > >
> > > Perhaps there is a better way to do this
> > >
> >
> >
> >
> 
> 
> 
> 



  • Prev by Date: RE: pbms with Mathematica 4.1 under Windows (copy paste ? comments?)
  • Next by Date: things to do before reinstalling linux
  • Previous by thread: Re: exchanging 2 elements in a list (problem with Block)
  • Next by thread: Re: Re: exchanging 2 elements in a list (problem with Block)