For the case of Block
and Module
one can choose to define values in the body for the variable names being scoped. So there is no restriction for one scoped variable to depend on others, as you can just do it in the body with proper SyntaxInformation
.
But for the case of With
, since there are technically no variables, the value needs to be set at the point of declaration so there is no way to have a dependence structure for the scoped names within the body. So the next best alternative is to have nesting within the With
by using more than 2 arguments.
With[{y=x},{z=y},{a=z},{b=a},b]
But the front end apparently is not recognizing this syntax which makes the argument three and onwards red, making the code hard to read. So I tried the following:
Unprotect[With];
SyntaxInformation[With]={"ArgumentsPattern"->{{__}..,_}};
Protect[With];
But it is not working. Can someone please help me fix this. Also in addition to fixing the argument highlighting. Is there a way to fix the scoped name colour to be green when there are nested dependencies.
I am adding these examples to add a little more clarity and detail:
First, let's look at Block
:
Block[{y=x,z=y,a=z,b=a},{x,y,z,a,b}]
{x, x, x, x, x}
It produces the correct output but actually it not doing dependence correctly. What it is actually doing is setting z
to the global value of y
, not the local value defined before. But since Block is dynamically scoped it can do localization at runtime and thus still manages to produce the correct result. This will fail if y
was globally defined.
But we can get around this limitation by defining the values in the body and keeping the declaration separate in the first argument:
Block[{y=x,z,a,b},z=y;a=z;b=a;{x,y,z,a,b}]
{x, x, x, x, x}
Note: Since Block
is dynamically scoped, this Block[{y=x,z:=y,a:=z,b:=a},{x,y,z,a,b}]
will also work but syntax coloring compromise would need to be made.
Now for the case of Module
:
Module[{y=x,z=y,a=z,b=a},{x,y,z,a,b}]
{x, x, y, z, a}
The above doesn't work as Module
is lexically scoped so at runtime it can't look in the OwnValues
to match local variables (Which is achieved by tagging the local variable names by $ModuleNumber
so they are completely shielded from their global counterparts if they exist). Again the fix is, just define dependence in the body, and SyntaxInformation
is correct as well:
Module[{y=x,z,a,b},z=y;a=z;b=a;{x,y,z,a,b}]
{x, x, x, x, x}
Now for the case of With
which the question is targeting.
With[{y=x,z=y,a=z,b=a},{x,y,z,a,b}]
{x,y,z,a,b}
What With
is doing is called scoped replacement. Which can be seen by comparing it with an explicit replacement.
Function[x, e] /. e :> x
Function[x, x]
When the unscoped variable x
gets replaced for e
it is automatically aligned with the locally scoped variable x
for the Function
. But doing the same replacement with With
:
With[{e := x}, Function[x, e]]
Function[x$, x]
Wolfram language changes the variable name for the locally scoped variable name x
for the Function
so it doesn't conflict with the incoming globally scoped x
via With
.
As a result since With
is just doing the replacement, it doesn't need any localized variable but just tags for local values so they can be referred inside the body. As a result, the above workarounds for Block
and Module
are not possible for With
:
With[{y=x,z,a,b},z=y;a=z;b=a;{x,y,z,a,b}]
With::lvws: Variable z in local variable specification {y=x,z,a,b} requires a value.
So the nesting syntax for With
can be used to achieve this (which as of 12.1 is still undocumented, I only knew this because it was mentioned in one of the Stephen Wolfram's LiveCEOing session):
With[{y=x},{z=y},{a=z},{b=a},{x,y,z,a,b}]
{x, x, x, x, x}
But the front end doesn't recognize this syntax as a result, this question. As pointed out by @MarcoB it was already discussed in another question asking for the alternative to explicit nesting of With
here which shows the picture of the problem as well. I didn't see this question earlier but I don't think my question is a duplicate since the resolution of SyntaxInformation
wasn't the point of that question.
With@@Hold[{a=3},{b=a+1},{c=(a+b)^2},{a,b,c}]
$\endgroup$