9
$\begingroup$

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.

$\endgroup$
-1
$\begingroup$

The pattern for the built-in is

Mathematica documentation

With in the Mathematica documentation.

In case You intend to enter more

use

With[{v = {a, b, c}, w = {x, y, z}}, Thread[Unevaluated[Dot[v, w]]]]

this will work without error. In words, put a curly bracket around Your values and make them a comma separated list:

With[{y=x,z=y,a=z,b=a},b]

will return

a
| improve this answer | |
$\endgroup$
  • 2
    $\begingroup$ (-1) The question is just not about this, to understand what's discussed in the question, please start from here: mathematica.stackexchange.com/a/54874/1871 $\endgroup$ – xzczd Jun 14 at 12:18
  • 2
    $\begingroup$ I don't think it's fair to downvote as the question doesn't explicitly acknowledge it's using undocumented behaviour. Showing the correct documented usage of With is valid and good advice for any passers by who do not know of the undocumented behaviour of nested-With and are wondering why red highlighting appears, but their code is working strangely. And as xzczd points out, this highlighting issue has already been addressed in other questions. $\endgroup$ – flinty Jun 14 at 14:23
  • 2
    $\begingroup$ @flinty This answer appears to misunderstand the question entirely. In particular, it does not even acknowledge that the usage in the OP works, although undocumented. A casual passer-by seeing this upvoted would conclude that the OP usage was just incorrect and miss out on a useful feature. $\endgroup$ – MarcoB Jun 15 at 0:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.