Re: Delayed symbol resolution

*To*: mathgroup at smc.vnet.net*Subject*: [mg122724] Re: Delayed symbol resolution*From*: "Oleksandr Rasputinov" <oleksandr_rasputinov at hmamail.com>*Date*: Mon, 7 Nov 2011 05:54:55 -0500 (EST)*Delivered-to*: l-mathgroup@mail-archive0.wolfram.com*References*: <j95p5g$m5l$1@smc.vnet.net>

On Sun, 06 Nov 2011 10:56:48 -0000, Rui <rui.rojo at gmail.com> wrote: > A few scattered times in my not too long Mathematica history I've found > myself facing a similar simple problem that always required particular > attention to solve it. > The problem, in broad terms: needing to insert a symbol whose context is > the current context at the time the code is being evaluated. Of course, > this might mean the symbol could be used as an argument to a HoldAll > function that receives a Symbol, so it can't be evaluated. So I end up > using MakeExpression or ToExpression wrapping the result in Hold and > then doing some (to me) hard expression manipulation with Applies, > RemoveHolds and Replaces which results in a code that might work but is > far from neat and understandable. I might add, the heavy expression > manipulation and Holds and replacements and etc were never my strong > suit... > > So finally I'm doing what I should have done from the start: > * Ask here if there's a simple way to solve it > * Create a short function in a package. > > I'll do the second one right now, and if you make me realise it's > redundant I'll throw it away. If not, I'll share it. > > I'm thinking of something Block-like such as > WithDelayedSymbols[{x, y}, (* code using x and y*)] > where every appearance of x and y would be replaced by the current > context symbols of ToExpression[x] and ToExpression[y] prior to any > evaluation. > Also, a > BlockDelayedSymbols[{x, y}, ...] which also adds dynamic scoping like > Block > > Rui Rojo > I'm not sure that I can suggest any general solutions to your problem, so I will just comment here that I make heavy use of With and rarely come across these sorts of issues. (For function arguments, Evaluate is often more appropriate than With.) In the (in my experience, rare) cases for which With is not sufficient, and where a pattern can be found to refer to the important parts of the expression, you can use the following approach combining With and either ReplaceAll or ReplaceRepeated (that I learned of from Ted Ersek, but which he states was invented by Michael Trott and Adam Strzebonski). This has been mentioned several times already by other posters, but I thought it would be useful to provide a little extra functionality via options: EvaluatePattern[expr_, patt_, opts___] := Module[{holdTemporary}, If[TrueQ[Hold /. {opts} /. Options[EvaluatePattern, Hold]], SetAttributes[holdTemporary, HoldAll] ]; Identity @@ ReplaceRepeated[ holdTemporary[expr], p : patt :> With[{eval = p}, eval /; True], MaxIterations -> ( MaxIterations /. {opts} /. Options[EvaluatePattern, MaxIterations] ) ] ]; Attributes[EvaluatePattern] = {HoldFirst}; Options[EvaluatePattern] = { MaxIterations -> $IterationLimit, Hold -> False }; As a usage example, we could try inlining nested functions. This might be useful as a preprocessing step for Compile, as the CompilationOptions setting "InlineExternalDefinitions" doesn't deal with nested definitions: In[5] := f=Function[{x},x]; g=Function[{y},f[y]]; h=Function[{z},g@f[z]]; k=Function[{w},h@g@f[w]]; In[9] := SetSystemOptions["CompileOptions"->"CompileReportExternal"->True]; In[10] := Compile[{u},k[u],CompilationOptions->"InlineExternalDefinitions"->True] During evaluation of In[10] := Compile::extscalar: h[g[f[Compile`FunctionVariable$244]]] cannot be compiled and will be evaluated externally. The result is assumed to be of type Integer. >> Out[10] = CompiledFunction[{u},Function[{w},h[g[f[w]]]][u],-CompiledCode-] In[11] := EvaluatePattern[ Compile[{u},k[u]], sym_Symbol/;Head[sym]===Function, Hold->True ] Out[11]= CompiledFunction[{u},Function[{w},Function[{z},Function[{y},Function[{x},x][y]][Function[{x},x][z]]][Function[{y},Function[{x},x][y]][Function[{x},x][w]]]][u],-CompiledCode-] Although the second CompiledFunction looks more complicated, if you look at the compiled code you will see that in fact the expression optimizer has removed all of the function calls and reduced it to a series of assignments that end up simply returning the argument.