Message Boards Message Boards

0
|
5908 Views
|
16 Replies
|
0 Total Likes
View groups...
Share
Share this post:

Trouble understanding the local variables of the Block command

I'm having trouble understanding the local variables of the Block command. Thanks for your attention

(*example one*)
(*This is said in the documentation*)
(*Blocklocalizes values only;it does not create new symbols*)
(*I don't understand the previous sentence*)
ClearAll["Global`*"];
Block[{x}, x]
Block[{x}, Print[x]]

(*example two*)
(*This is an example of the documentation.*)
(*But if one of x or y is global the example does not work*)

ClearAll["Global`*"];
Block[{f = Sin[x + I y]},  ParametricPlot[Evaluate[{Re[f], Im[f]}], {x, -Pi, Pi}, {y, -2, 2},   Mesh -> 10]]

(*example three*)
(*I would like the block to work regardless of whether x is global or not*)

ClearAll["Global`*"];
Block[{x},
 TraditionalForm@TextCell[Column[{
     Row[{x, " = ", 5}]    (*I want x to always be a symbol*)
     }, Spacings -> 0.5], "Text", FontFamily -> "Palatino",    FontSize -> 18]
 ]
Attachments:
POSTED BY: Ernesto Espinosa
16 Replies
Posted 2 years ago

You say you "want x to always be a symbol", but all symbols will be replaced with their assigned values (OwnValues) if they exist, so this can't actually be done, per se. What you can do, however, is apply one of the various Hold* functions. Probably HoldForm is what you want in this case, and you don't need the Block for this:

TraditionalForm@
 TextCell[Column[{Row[{HoldForm[x], " = ", 5}]}, Spacings -> 0.5], 
  "Text", FontFamily -> "Palatino", FontSize -> 18]

This might have undesirable implications if you do further processing of the result, but I would need more information to help you address any of those issues.

Extra info about Block

Inside the Block, x will have its OwnValues temporarily overridden. But once the Block finishes executing the OwnValues for x will revert to its previous value. Execution continues until nothing in the expression changes, so any x remaining after Block finishes will get replaced by the "original" OwnValues definition.

Let's play with this:

x = 7;
Block[{x = 5},
 {OwnValues[x], Hold[OwnValues[x]]}]

This returns

{{HoldPattern[x] :> 5}, Hold[OwnValues[x]]}

Now try:

ReleaseHold@%

This returns

{{7 :> 5}, {HoldPattern[x] :> 7}}

POSTED BY: Eric Rimbey
Posted 2 years ago

Eric: I am writing text to display on the screen with a fixed format. Files for students of Differential Equations with interactions using Manipulate. If in a Block its local variables have no value, I don't understand why they are not treated as symbols. I know the answer is by design of the Mathematica team. It doesn't match my intuition. I see that if x is global with no value or x does not exist in the global my proposed code works. That is, I get what I want with OwnValues[x] = {}. HoldForm[x] inside the code always works but my code would be horrible and laborious. I basically don't want problems with global variables. Ernesto

POSTED BY: Ernesto Espinosa
Posted 2 years ago

If in a Block its local variables have no value, I don't understand why they are not treated as symbols.

If the variable definitions in the Block have no OwnValues, then they are treated as symbols. This has nothing to do with Block. The problem is that the expression you're creating inside the Block will be outside the Block once the Block is done. Once it's outside the Block, the evaluator continues to do its evaluating, and when it sees the x it will look for OwnValues for that x.

If you're not going to need to evaluate/manipulate the expression later, then you don't need a raw symbol. You can use a string, or you can wrap the symbol in HoldForm. Why would that not work in your case?

Also, SymbolName might be a cleaner way to generate a string from the symbol.

POSTED BY: Eric Rimbey
Posted 2 years ago

HoldForm[x] inside the code always works but my code would be horrible and laborious.

I don't understand why this would be the case. It seems a lot simpler than creating a whole Block expression. The situation is that you have a symbol that, instead of being evaluated with its OwnValues, you want to display in a nice way. That's exactly what the *Form functions are intended to do.

POSTED BY: Eric Rimbey

Eric: “If the variable definitions in the Block have no OwnValues, then they are treated as symbols.”

This is valid if x is not global with value.

“You can use a string, or you can wrap the symbol in HoldForm. Why would that not work in your case? Also, SymbolName might be a cleaner way to generate a string from the symbol.”

I have at least 20 lines of code inside each Block that contain many mathematical symbols and I want them not to be evaluated if they are global, since they are use in expressions to read not to evaluate. I have hundreds of Blocks to use HoldForm or SymbolName. It would leave my code unreadable. I cannot use strings because the format of the variables is lost. My suggestion is that if x is a Block local variable and no value is assigned to it, this variable is treated as a symbol.

Ernesto

I appreciate your attention and kindness.

POSTED BY: Ernesto Espinosa
Posted 2 years ago

I'm realizing that we're rat-holing on the wrong things. You titled your post, Trouble understanding the local variables of the Block command, and so I've been trying to explain how Block works. But that's not your actual problem. Your actual problem seems to be something like, How can I display mathematical expressions nicely when they involve symbols that might have OwnValues? And furthermore, you want an approach that is repeatable hundreds of times. I'm confident that there are ways to do that that are simpler and more readable than the approach you've taken. But I don't want to start giving you suggestions only to have you tell me "that works fine with one variable, but my context is complicated". At this point, I suggest that you give us a representative example of a formatted output that you'd like to be able to generate. Include information about which symbols have OwnValues.

POSTED BY: Eric Rimbey

Here is an example of my code. (Eric.nb)

What I want as result (Test.nb]

Attachments:
POSTED BY: Ernesto Espinosa
Posted 2 years ago

Excellent! Thanks!

So, just to make sure I don't go down the wrong trail, I have some clarifying questions:

POSTED BY: Eric Rimbey
Posted 2 years ago

Another question:

  • Are you familiar with how to use style sheets?
POSTED BY: Eric Rimbey
Posted 2 years ago

Ernesto, I'm very confused. I've looked through Test.nb more thoroughly, and I don't see any reason why any of the textual content can't be just static content. I mean, you could programmatically assemble a notebook with the content, maybe piece together larger content from smaller snippets, but I can't see any reason why it can't just be something like static text cells with embedded cells for the mathematical expressions. I see that you have some controls for navigation, some TabViews and so forth, but none of that seems to depend on any of the symbols being used in the expository content.

I started trying to refactor your example (dDiv, dEx, etc), but when I started matching it up to the content in Test.nb, it just wasn't making any sense. What am I missing? I feel like I've just completely misunderstood your question here. It doesn't seem to have any bearing on the content in Test.nb.

POSTED BY: Eric Rimbey
Posted 2 years ago

Ernesto,

I think what you want is to do something like this:

Block[{x}, 
 TraditionalForm@
  TextCell[
   Column[{Row[{ToString[x, TraditionalForm], " = ", 
       5}]    (*I want x to always be a symbol*)}, Spacings -> 0.5], 
   "Text", FontFamily -> "Palatino", FontSize -> 18]]

You can see what the problem is by looking at the FullForm of your expression returned from the Block:

blk = Block[{x}, 
   TraditionalForm@
    TextCell[
     Column[{Row[{x, " = ", 
         5}]    (*I want x to always be a symbol*)}, Spacings -> 0.5],
      "Text", FontFamily -> "Palatino", FontSize -> 18]];

blk // FullForm

The Block clears the local value of x so it can be used as a symbol or reassigned locally as you want to do. However, after it is returned to the front end, it still has the variable form of x inside. This causes Mathematica to reevaluate it in the global context and substitute the value for x. The way to fix this is to "lock down" the symbol x so it doesn't get reevaluated. Since you only seem to want a string in the end that has the traditional form of the variable, I would use the local value of x (a symbol) and convert it to a string in traditional form. At this point it will no longer be reevaluated.

I hope this helps,

Neil

POSTED BY: Updating Name

In fact, you can simplify it further by doing this:

Block[{x, y}, 
 TextCell[
  Column[{ToString[x''[t]/Sqrt[x + y] == 5 y , 
     TraditionalForm]  (*I want x to always be a symbol*)}, 
   Spacings -> 0.5] , "Text", FontFamily -> "Palatino", 
  FontSize -> 18]]

You do not need to do any detailed string manipulation and you can put in any arbitrarily complex expression.

Regards

Neil

POSTED BY: Neil Singer
Posted 2 years ago

You also don’t need the Block, as I’ve been trying to explain to the OP:

ToString[Unevaluated[x''[t]/Sqrt[x + y] == 5 y ], 
     TraditionalForm]

The OP seems to very much want to deal with cells and boxes for some reason.

POSTED BY: Eric Rimbey

Gracias Eric

POSTED BY: Ernesto Espinosa

Here's a general workflow for blocking values of global variables while output is prepared. Before the output is returned, the global variables need to be protected from evaluation. HoldForm is the way to do this and have the variables be typeset in their usual format.

x = 3; y = 7; (* to see if x appears as x *)

(** hold variables to be used in formula/output **)
heldvars = Hold[x, y];
(* use stored variables in heldvars to Block their values *)
heldvars /. Hold[$v___] :> Block[{$v, res},
   (** possibly lengthy code to compute result `res` **)
   res = Column[{x''[t]/Sqrt[x + y] == 5 y}, Spacings -> 0.5];
   (* protect variables with HoldForm before returning *)
   res = res /. {var : Alternatives[$v] :> HoldForm[var]};
   (** format result **)
   TextCell[
    TraditionalForm@res,
    "Text", FontFamily -> "Palatino", FontSize -> 18]
   ]

The lines of code after the comments between the double asterisks (**...**) are user-supplied and would probably change from case to case. The lines of code after the comments between the single asterisks (*...*) should be the same in all use-cases (that I've thought of). One exception might be whether to block the variable res. It might be left global or it might be localized in a Module instead of in Block. Similarly, but more importantly, you shouldn't use $v as a variable in the computation of res, since it was used as a pattern name.

POSTED BY: Michael Rogers
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract