5
$\begingroup$

I need to use local indexed variables inside With but it is not allowed, the same for Block and Module. The following codes return an error.

What can be done in this case since I already have large expressions with indexed variables.

With[{a[1] = 7}, Print[a[1]]]
Block[{a[1] = 7}, Print[a[1]]]
Module[{a[1] = 7}, Print[a[1]]]

"Local variable specification {a[1]=7} contains a[1]=7, which is an assignment to a[1]; only assignments to symbols are allowed."

On one hand they recommend not to use code like ToExpression["a" <> "1"] which produces variable a1 but instead it is advised to use indexed variable a[1].

On the other hand when you did it that way you find out that they are useless with With.

$\endgroup$
9
  • $\begingroup$ You do Module[{a}, a[1] = 7; Print[a[1]]]? $\endgroup$
    – Domen
    Commented Oct 17 at 19:24
  • 3
    $\begingroup$ I'm tempted to vote to close. I don't think you've provided enough information to explain what the impedance is in your current situation. It's not clear to me why you'd even bother with your ToExpression["a"<>"1"] strategy when you're wanting to "localize" variables in Module, Block, or With anyway. I don't think "isn't it ridiculous?" is a legitimate question for this forum. I could come up with several ways to create some sort of indexing within these structures, but there isn't nearly enough information here for me to provide clear explanations or guidance. $\endgroup$
    – lericr
    Commented Oct 17 at 21:14
  • 1
    $\begingroup$ Somewhat related: mathematica.stackexchange.com/q/32648/1871 mathematica.stackexchange.com/q/285628/1871 "…it is advised to use indexed variable…" Yeah so I myself tend not to make such advice these days. BTW is it an official advice? I'm under the impression that this is just something frequently suggested by some experienced users. $\endgroup$
    – xzczd
    Commented Oct 18 at 0:25
  • 1
    $\begingroup$ @xzczd I think the advice about indexed variables is being taken to broadly and too literally. The most common situation where that advice is given is as an alternative to Subscript. Subscript is really a formatting utility and doesn't really lend itself to the use of just "subscripted variable" like people want it to be--like one could write on a chalkboard in math class. $\endgroup$
    – lericr
    Commented Oct 18 at 19:42
  • 1
    $\begingroup$ @xzczd Furthermore, in any programming language, creating list of variables like a1, a2, a3..., is a code smell. You can't say it's always bad programming, but it's bad often enough that you should be suspicious. 99% of the time, the semantic that is desired can be better represented by Indexed, Part, or down-values, or something else entirely. $\endgroup$
    – lericr
    Commented Oct 18 at 19:47

2 Answers 2

9
$\begingroup$

Maybe you can make use of the internal function LocalizedBlock:

ClearAll[LocalizedWith];
SetAttributes[LocalizedWith,HoldAll];

LocalizedWith[vars:{__Set}, body_] := Replace[
    Extract[Unevaluated @ vars, {All, 1}, Hold],
    Hold[v_] :> Internal`LocalizedBlock[v, vars; body]
]

Then:

LocalizedWith[{a[1]=7}, Print[a[1]]]

7

$\endgroup$
2
$\begingroup$

We may use temporary global indexed variable b and assign its value to a inside With. This way we can work with local indexed variable a inside With without affecting global a.

Clear[b]
Evaluate@Array[b, 3] = {7, 11, 3};
With[{a = b}, Print[a[1]]]
Clear[b]

7
$\endgroup$
9
  • 4
    $\begingroup$ If you're willing to use the Global context for temporary variables, then why bother with the With at all? $\endgroup$
    – lericr
    Commented Oct 17 at 21:36
  • 2
    $\begingroup$ @lericr I am willing to use local indexed variable a inside With. I think this is clear enough from the title and the question itself. $\endgroup$ Commented Oct 18 at 8:52
  • 1
    $\begingroup$ @Domen I do not understand your concern. You do not have to clear b if you do not wish. What is the point? You can forget about b once you have done computation inside With or several Withs, it does not matter if you leave b set or you clear it because you will never use it again. Your suggestion was to use Module[{a}, a[1] = 7; Print[a[1]]]. If a is an array of say 1000 values I think you do not expect me to type them by hand. You would need a similar solution like Module[{a}, a = b; Print[a[1]]] with global b being an array of length 1000. $\endgroup$ Commented Oct 18 at 11:33
  • 1
    $\begingroup$ @Domen If your concern was like you accidentally clear b while still computation in With was not done then simply name it not b but tempVariableNeverUsedAgain and the chance of you accidentally use the same name of variable for other purpose is negligible. $\endgroup$ Commented Oct 18 at 11:39
  • 1
    $\begingroup$ @lericr Interpreting the question as being about Print needs a lot of ignorance (intentional or unintentional?). azerbajdzan, I have just encounter the same problem with using indexed variable with With, which seemed to be impossible but your answer helped me a lot. $\endgroup$
    – three777
    Commented Oct 19 at 9:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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