Re: locally changing Options
- To: mathgroup at smc.vnet.net
- Subject: [mg108356] Re: locally changing Options
- From: Raffy <adraffy at gmail.com>
- Date: Mon, 15 Mar 2010 00:05:12 -0500 (EST)
- References: <hnie2u$et$1@smc.vnet.net>
On Mar 14, 3:34 am, Leonid Shifrin <lsh... at gmail.com> wrote: > Hi, > > > Anyway, after thinking about it, I felt that the simple fix would be: > > Block[{RowReduce=System`RowReduce[#1,Method->...,##2]&}, ...] > > In[107]:= Print === System`Print > > Out[107]= True > > (I ran this code before running your example with Temp`Print, after which > Print got shadowed and this gave False). > > Since Block scopes dynamically, it obeys the same rules. The scoped symbo= l > is the one currently first on the $ContextPath (if it exists in the symbo= l > table), while the value it is assigned during the initialization in Block > can be anything, including the symbol itself. My guess is that droppin= g the > fully qualified name in the Trace is just the usual output formatting: > behind the scenes we always deal with System`RowReduce (or whatever our > symbol is). In particular: > > In[108]:= Block[{RowReduce}, > Context[RowReduce]] > > Out[108]= "System`" > > > However, this also results in recursion. Something seems odd: how is > > the blocked RowReduce scoping the fully qualified symbol > > System`RowReduce? (Looking at the Trace, it appears that it is > > dropping the System` context prior to evaluation...) > > The statement Block[{x=x}, body] seems to make sense only if x has a gl= obal > OwnValue, otherwise (if it has DownValues or other ...Values instead) it > seems idle to me - that is, equivalent to just Block[{x}, body]. So, for = the > purposes of Block Print and System`Print are identical - that is, the cod= es > > Block[{Print = System`Print}, Print[1]]; > Block[{System`Print = System`Print}, Print[1]]; > Block[{Print = Print}, Print[1]]; > Block[{Print}, Print[1]]; > Block[{System`Print}, Print[1]]; > > are all equivalent (assuming you did not shadow System`Print by importing > some context with another Print). The printing happens not inside the Blo= ck > anyway (since inside the Block Print forgets what it is), but the moment = we > leave it. Proof: > > In[109]:= > ClearAll[f]; > f[Unevaluated[Print[x_]]] := {"Value: ", x}; > > In[111]:= Block[{Print = System`Print}, f[Print[1]]] > > Out[111]= {"Value: ", 1} > > Since <f> does not hold its arguments, Print[1] would evaluate if it P= rint > "knew what to do", and the rule in <f> would not match, just as it happen= s > below, without the Block: > > In[112]:= f[Print[1]] > > During evaluation of In[112]:= 1 > > Out[112]= f[Null] > > > > > This works: Block[{Print=System`Print},Print[1]]; > > This doesn't: Block[{Print=System`Print[##] &}, Print[1]]; > > This has probably nothing to do with Block specifically, and can be model= ed > in a simpler setting. > > Here we model the code <Block[{Print = Print}, Print[1]]> > > In[113]:= > Clear[f]; > f = f; > f[1] > > Out[115]= f[1] > > and here the code <Block[{Print = Print[##] &}, Print[1]]> > > In[116]:= Clear[f] > f = f[##] &; > f[1] > > During evaluation of In[116]:= $IterationLimit::itlim: Iteration limit = of > 4096 exceeded. >> > > Out[118]= Hold[f[1]] > > This suggests that this effect is due to the differences in evaluation= in > these two cases, rather than specifically tied to Block. In the second > method, infinite iteration is likely due to the fact that expression is > oscillating between the forms f[1] and f[##]&[1]: after each > parameter-passing stage, evaluator gets a new expression (f[1] instead of > f[##]&[1]), and since it has changed, evaluator re-evaluates it, which ag= ain > results in f[##]&[1]. > > > > > Really odd behavior can be found using the following: > > Let $ContextPath = { ..., "Temp`", ..., "System`", ... } > > Block[{Temp`Print=System`Print[1, ##] &}, Print[2]] will print "12" > > and also cause Print to become shadowed. > > Indeed, odd enough. If a symbol did not exist in some context, but we dec= ide > to use it in Block, I'd expect Block to clean up, namely return everythin= g > to the way it was before Block has been called. In particular, it should > have removed this symbol from the symbol table at the end, so that there > would be no shadowing after Block has finished. The question is whether t= his > is a bug or a feature (intended design decision) - I have no idea alas. > > Regards, > Leonid > > > > > > > I guess the problem boils down to: Why does System`Print simplify to > > Print? Leonid thanks for all the input. However, not to beat a dead horse, I'd like make another point. I thought Block[ {x = ...}, body ] was the equivalent of: Block$1234`x = ... $ContextPath = Prepend["Block$1234`", $ContextPath]; body $ContextPath = Rest[$ContextPath]; Remove["Block$1234`*"]; (which would be essentially how dynamic scoping in general is performed: you pushing a new resolver on your lookup stack.) That way, if body was, Print[x + 1], x gets resolved to Block$1234`x and prints 2. Or, with my example from before: Block$1234`f = System`f[1, ##]&; $ContextPath = Prepend["Block$1234`", $ContextPath]; Print[f[2]]; $ContextPath = Rest[$ContextPath]; Remove["Block$1234`*"]; Where f[2] => Block$1234`f[2] => System`f[1,2] But it appears that Block[ {x = ...}, body ] is instead figuring out which long variable it's scoping based on the current context and then blocking that. While they gives a similar effects, it seems the latter is far less useful, because the programmer loses the ability to reference a symbol with a fully known context path. (It also seems like you could create a really nasty example of nested Blocks with Context changes but I can't think of it right now.) It's good that I now know Block[] is not doing what I expected, I just wished it performed like my first example. This would give the programmer the ability to "unblock" by just using the long symbol name.