Message Boards Message Boards

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

Difference between Module and Block?

Posted 2 days ago

i have been spend an hour in order to find the difference of Module and Block function but failed. if i regard this two function as a black box, it seems their function is the same . Could anyone share me a example to explain the difference of them.

POSTED BY: Martin Xia
5 Replies

POSTED BY: Martin Xia

Here are some examples that show a difference between Block and Module. I hope including many examples in each code is not confusing. I've organized them in a grid to aid the comparison.

Clear[a, x, y, f, ff, g, h];
f = a x^2;
g = a y^2;
h = a z^2;
y = 4;
Grid[{
  Thread@HoldForm@{Command, "", x, y, z, a, "", f, ff, g, h'},
  Block[{x = 3, y = 5, z, a, ff}, ff = a x^2;
   {Block, "", x, y, z, a, "", f, ff, g, D[h, z]}],
  Module[{x = 3, y = 5, z, a, ff}, ff = a x^2;
   {Module, "", x, y, z, a, "", f, ff, g, D[h, z]}]
  }, Dividers -> All]

enter image description here

Below, the Hold[..] shows the values before evaluation exits the Block/Module, and it is followed by what the values evaluate to outside the Block/Module. There is no change after exiting Module, but there can be after exiting Block. When Block returns an expression, any blocked variables get their values back and the returned expression is reevaluated.

x = 7;
Grid[{
  Block[{x},
   {x, f, D[f, x]} // {Block, "", Hold[#], #} &],
  Module[{x},
   {x, f, D[f, x]} // {Module, "", Hold[#], #} &]
  }, Dividers -> All]

enter image description here

Point of comparison:

  • In Block[], the block variables refer to the same variables outside the Block. However, at the beginning of Block[], the values or definitions of the variables are cleared. When Block[] exits, the block variables are reset to their values or definitions. This may trigger a reevaluation.

  • In Module[], the module variables do not refer to the same variables outside the Module. Definitions made before the module will refer to variables outside the Module[] and will not refer to the module variables. In definitions made inside the module, the literal appearance of variables will refer to the module variables. Example:

 

Clear[a, x, f];
f = a x^2;
Module[{x, ff}, ff = f; {x, ff}] (* no literal appearance of x in "ff = f" *)
Module[{x, ff}, ff = a x^2; {x, ff}]; (* x literally appears *)
(*
{x$27343, a x^2}        <-- external x
{x$27344, a x$27344^2}  <-- module x
*)
  • Block[] is used to prevent a formula from having a value substituted into a variable, either prematurely or at all. This was useful in the second example for finding the derivative. Plot[] effectively uses Block[] for this purpose so that x=5; Plot[2 x^2, {x, 0, 2}] plots the parabola $y=2x^2$ and not the line $y = 50$ (the value of $2x^2$ at $x=5$).
POSTED BY: Michael Rogers
Posted 1 day ago

The documentation discuss Module versus Block here

POSTED BY: Hans Milton

Thank you, Eric. i still can not distinguish them.however, your general advice gives a rule which i can follow in future. Thank you!

POSTED BY: Martin Xia
Posted 2 days ago

This is actually quite an involved topic. We need to take a step back. In many languages, the concept of localization involves a scope. Variables are declared within a scope and they cannot be referenced outside of that scope. In Mathematica, there is no true scoping mechanism. Any variable can be accessed from anywhere. But there are times where localization is really useful. So, Mathematica has a way to "fake" localization. It does this through naming conventions. If you've encountered the idea of Context before, this is what I'm referring to. A variable has a fully qualified name that includes its context, but you only need to use the short name for most purposes. In a fresh session, if you type a variable like x, the full name of that variable is actually Global`x. Most of the built-in symbols we use regularly, like Plot, are in the System context, so Plot is actually System`Plot.

Okay, so we need some sort of localization mechanism. Sometimes localization happens "silently" (like when you use Set or SetDelayed) through the specific way evaluation happens. But when you need a more involved localization mechanism, you have three options: With, Block, and Module.

With is the easiest. It's a lexical replacement mechanism. That means that before any evaluation occurs, the "local" variables you've defined are replaced throughout the body of the With. It's like those "local" variables never even existed.

Module does some magic. Unbeknownst to the user, Module actually renames all of the local variables you've defined before it does anything else. This avoids naming conflicts and makes it seem like your variables are actually scoped to the Module. Try the following very simple example:

Module[{a}, a]

The output will be something like

a$4981

(the actual value depends on the state of your session at the time the Module is evaluated). And the full name of this variable is

Global`a$4981

Since it's unlikely that you will ever intentionally define a variable like a$4981, this has the effect of scoping that variable to the Module (but it's actually not truly enforced).

Okay, so what's the deal with Block? Block basically sets up a new environment that allows you to define variables, and whatever variables you define override any pre-existing variables within the Block. It's really the closest thing to a local scope that you can get in Mathematica. The main use case for Block is for side effects. You generally want to temporarily set some important system variable to a new value, but you want to be careful that this new definition isn't permanent. So, for example, my current timezone offset is -8. If I do this:

DateObject[]

I get something like this:

DateObject[{2024, 11, 18, 20, 3, 34.943531`8.295941767663606}, "Instant", "Gregorian", -8.]

If I want to mimic being in GMT, I could do this:

Block[{$TimeZone = 0}, DateObject[]]

and get

DateObject[{2024, 11, 19, 4, 4, 51.22838`8.462085597606766}, "Instant", "Gregorian", 0.]

If you don't provide an explicit option for DateObject, it will base the result on the value of

$TimeZone

set on your machine. So, we can override that side effect within Block, but not worry about it being permanent. Notice that $TimeZone never explicitly appeared inside my Block expression, but since that variable is silently used by DateObject, we get the desired effect.

Here is the general advice...

If you just want some sort of local constant, maybe to avoid duplication or to avoid calculating something multiple times, use With. Basically, always use With unless it just won't work for your situation. The next option is Module. Use Module if your "local" variables are not constant, but in fact need to be updated as part of your algorithm. Just be aware that you won't have access to these variables outside of the Module unless you somehow capture their fully qualified names. Only use Block when you want to temporarily reset a variable's value. Typically this is for System variables, but sometimes you will want to do this with your own user-defined variables. Maybe you're testing something, for example. You could always use Block if you want, but there are weird situations where things might not work as you expected. So, I prefer With, then Module, then Block.

POSTED BY: Eric Rimbey
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