Hot answers tagged

58

Internal`InheritedBlock (IIB) is similar to Block, except that it preserves the original definition of the function being passed to it. The function can then be modified as we wish inside the IIB without affecting the external definition. Let's see how Block works first: f[x_] := x Block[{f}, Print@DownValues[f]; f[x_, y_] := x y; Print@...


46

Introduced in V10.4 or earlier, but after V10.1 This functionality has snuck into With (ref: Daniel's comment). Note the use of the braces. With[{v1 = #}, {v2 = f[v1]}, g[v1, v2]] (* g[#1, f[#1]] *) The syntax coloring has not caught up yet: In V10 -- Needs["GeneralUtilities`"]; ?GeneralUtilities`Where Where[ass1, ass2, ..., expr] is a version of ...


46

You are correct about the behavior of computations done from preemptive links. So-called "preemptive evaluations" have been around since version 6. They are a class of evaluations that all work through the same mechanism. When Mathematica checks to see if a user interrupt has been requested, which it does at a high rate most of the time, it also looks to see ...


35

Internal`LocalizedBlock behaves the same as Block, but it can localize non-Symbols (e.g. f[1], Subscript[x, 0], etc.). For example, Internal`LocalizedBlock[{Subscript[x, 0]}, Subscript[x, 0] = 1] (* 1 *) Compare this to Block[{Subscript[x, 0]}, Subscript[x, 0] = 1] (* During evaluation of In[79]:= Block::lvsym: Local variable specification {Subscript[x, ...


32

Short answer The local variables of the form varname$... are used by the system, and it is unwise to use symbols with such names as local variables. With, like many other lexical scoping constructs, performs excessive renamings, often even in cases where it isn't strictly necessary. This probably has to do with efficiency - full analysis may be more costly. ...


28

Preliminaries As Todd has indicated in his answer which has a lot of excellent information, the situation where the described behaviour will actually trigger problems will be very rare. I also read from his answer that WRI doesn't consider this behavior to be a bug and my hopes that this might change in future versions are low or nonexistent. I show ...


27

The short answer is "yes", we should always use Module to localize any intermediate variables within our functions. We might get away with using global variables for everything in an ad hoc, interactive session. But as we accumulate function definitions that we wish to re-use repeatedly over time, the chances of this practice causing problems increases ...


24

Version 12.2 In version 12.2, use the new function WithCleanup[]: With[{plotOptions = Options[Plot]}, WithCleanup[SetOptions[Plot, PlotStyle -> Green], Plot[Sin[x], {x, -π, π}], SetOptions[Plot, plotOptions]]] which is a direct replacement of the older undocumented function described below. Older versions Usual ...


23

What's happening This is not simple by any means. You have encountered another instance of a general situation with lexical scope leaks / emulation / over-protection by symbol renaming. The case at hand is pretty similar to the one discussed here, so you can read the detailed explanation of this behavior in my answer there. Roughly speaking, outer lexical ...


23

Preamble I will try to summarize some cases I've seen or encountered, in a few rules, which I believe do hold and explain most or all of the cases I am aware of. The rules Here are the rules (assuming that $HistoryLength is set to 0 and that there are no UI elements present on screen, or other code constructs - such as e.g. Internal`Cache object which one ...


22

In general, it is good practice to include i among the local variables. Table does not localize its variable (or, as some say, it only localizes the value but not the variable). It is relatively safe to leave i unlocalized when variables only have numeric values, like in fun. But the same is not true when variables can have symbolic values, e.g.: fun2[x_]...


22

A long comment: Automatic renaming again: ClearAll[F]; F[x_] := Hold[With[{a = x}, {b = x}, a]]; F[0] Hold[With[{a$ = 0}, {b = 0}, a]] I was expecting it already in DownValues, but this is not the case. DownValues @ F {HoldPattern[F[x_]] :> Hold[With[{a = x}, {b = x}, a]]} So who does it? :) Here is a pure guess, if evaluation is really a ...


21

Preamble What happens can be understood when we recall that Rule is a scoping construct. The general issues related to variable renamings in scoping constructs have been considered in more details in this answer. General Now, to this particular case. When the code runs, the external RuleDelayed considers the situation "dangerous" and performs variable ...


21

Based on Mr.Wizard's answer and comments by Szabolcs and celtschk, I now understand that the code I posted does have undesirable side-effects and it should be avoided. Specifically, the scoping constructs Module and Block are meant to completely localize the variables in their first argument (for more information see this question). However, placing their ...


20

What happens and why As Daniel Lichtblau pointed out in comments, this behavior can also be viewed as a flaw in the current behavior / design / implementation of lexical scoping in Mathematica. However, it may be useful still to understand on a deeper level what happens, since it can be explained rather easily from the core rules of how lexical scoping ...


20

Why is this happening The explanation was basically given by ciao in comments. You can also find a lot of information on this in this great answer of Mr.Wizard. I will perhaps try to view it from a somewhat different perspective. To understand what happens, one should go back and consider what happens when we enter and execute some code. The steps are ...


19

You need to use Module option on return myMod := Module[{i}, Do[ Return[1, Module], {i, 3} ]; Print["test"] ] and now myMod (* 1 *) This is because Return only returns from nearest enclosure, which was Do in your case and not from the whole Module unless you use the Module second option to Return. This is different from other languages ...


19

Looks like a bug to me as well. Just as Michael I would suspect that the problem is more with Lookup than Block or Associations in general. Here is a code example which seems to confirm that it is Lookup which does some caching and obviously doesn't take into account that the Blocked variables value has changed: ClearAll@test test[var_String] := Block[{...


17

To avoid those scoping constructs being recognized as such and having their variables renamed, I like wrapping their heads with Identity. In your case, func[opt_] := Identity[With][{a = True}, "x" /. opt]


17

I have used several methods, including the ones in the other answers. I have found that the simplest method is Internal`InheritedBlock as it allows for temporary changes to a symbol to be made, including changes to Options. For example, Internal`InheritedBlock[{Plot}, SetOptions[Plot, PlotStyle -> Red, Frame -> True]; Plot[Sin[x], {x, 0, 2 Pi}] ] ...


16

I think that this has been discussed many many times before, but it keeps popping up. So, I will state this once again: Do not allow functions' bodies to depend on symbols not passed to them explicitly If you follow this simple principle, you will be guaranteed that you will not see this sort of surprises. Here is a link to the detailed discussion on this ...


16

I will make no attempt to defend the fact that Mathematica simulates scoping by means of variable renaming. However, the behaviour that we see is consistent with the principles under which Mathematica does operate. Whenever Mathematica tries to interpret a symbol name, it first checks to see whether a symbol with that name already exists in a package in ...


16

There are multiple issues here. Let us take them one by one. Why do you get 0 as the output? There is a quirk in how DistributeDefinition works. To me, this looks like a bug ... Let me show it through a smaller example that isolates the problem. Let's define a function in a fresh kernel using Set instead of SetDelayed, then distribute its definitions, ...


15

Overview Here's two functions that operate in a manner close to what you want. The first uses a locally defined context to provide the scoping. The second uses Block, and is likely closer to what you wish. Version 1 Here's a single function that does what you want: ClearAll[Scope]; SetAttributes[Scope, HoldAll]; Scope[{globals : (_Symbol | _Set | ...


15

Usually, when one defines a function that's not too complex (usually a one-liner) it is customary (here we mean Mathematica custom) to define it directly without any scoping constructs (Module, With or Block). For example: myFunction[x_]:= 2 Sin[x] + Exp[-x^2] But as the function definition gets more complex, instead of polluting the Global context with ...


15

J. Fultz' answer indicates that it is not a bug but a feature which needs better documentation. Get a habit of defining your procedures with [], e.g. f[]:=Print[1]. (Which creates DownValues instead of OwnValues). DynamicModule saves its variables' OwnValues in the first argument of that DynamicModule. Which does not support SetDelayed and is sliently ...


15

Compile is considered a scoping construct by the outer With, and its bindings are protected. This will work: With[{args = {{x, _Real}}}, Hold[Compile @@ Hold[args, x + 2]]] or this (if you don't want to keep Apply in code): Unevaluated[ With[{args = {{x, _Real}}}, Hold[Compile[args, x + 2]]] ] /. Compile -> $compile /. $compile -> Compile ...


14

This is as designed (as it should be). In general, when you use Block[{s = someExpression}, body] then s is initialized with the value of someExpression, computed using the surrounding environment (usually Global` context). But then, all changes made to the properties of s, remain local to Block and are undone after the execution exits Block. In the ...


14

This is a documentation bug. Our source notebooks do contain documentation for experimental and future features, but they are supposed to be stripped in the process of being bundled with the product. In this case the bug is that the usage statement is marked as not to be included, but is still ending up in the built documentation. We apologize for the ...


14

This answer builds on @AlbertRetey's answer where, in the comments, you wanted some guidance as to how Wolfram creates robust controls. Think very carefully about the division of labor between the FE and the kernel. You've effectively embedded the entire implementation inside the FE by putting the update functions in DynamicModules. Generally, this is a ...


Only top voted, non community-wiki answers of a minimum length are eligible