Sorry if this is kind of a noob question but I'm wondering what the best-performing approach is to the following: I'd like to define several local constants in the body of a function, each of which depends on the value of the previous one(s) in an arbitrarily complicated way. My understanding is that e.g. when doing this with a single constant, the best thing to do is use With:
f[args___]:= With[{const = (* something *)},
(* body where the value of const may be used many times over *)
]
As I understand it, this is better (per the documentation for With) than using Block or Module more or less because Mathematica does not have to set up a local environment where the value of const may be repeatedly updated throughout the evaluation.
Now, suppose we want to write a function where there will be multiple local constants, each of which depends on the previously defined ones and each of which is used many times throughout evaluation. A very straightforward way to implement this would be to use one Block where we can mindlessly give names to all our constants and compute them in order, at the expense of forcing Mathematica to waste time pretending that these constants might be updated at some point in the evaluation of the function when in reality they won't. It seems that the solution using With forces us to use many nested With statements:
f[args___]:= With[{const1 = (* something *)},
With[{const2 = (* computation using const1 any number of times *)},
...
(* body where the values of all constants may be used many times over *)
...
]
]
Does anyone know whether there is some point (e.g. some number of such nested statements) where the overhead of nesting them like this might become more expensive than just using a flat Block structure? Or is it always advantageous in these situations to use With, however many nestings might be required? I would try to test this myself but I'm not confident I understand what's going on well enough to cover the appropriate ranges of test cases and to interpret the results.
Withs might provide a small performance benefit, but they are a maintenance nightmare: Code is much more cumbersome to debug because it has to be heavily refactored before one can be evaluated again step by step. At least for most of my tasks I get way better performance boost byCompile-ing the most performance critical piece of code. (Btw., I think the C-compiler is way better in exploiting constness than the Mathematica kernel -- even without declaring things as const. Simply because it is given way more time to mull over this.) – Henrik Schumacher Apr 26 '23 at 22:29LetLby Leonid Shifrin: https://mathematica.stackexchange.com/a/10451. – Henrik Schumacher Apr 26 '23 at 22:32Withsupports the (undocumented) syntaxWith[{x=3},{y=x^2},{z=x+y},...]– Daniel Lichtblau Apr 27 '23 at 00:35Compileis probably the best idea for a lot of what I'm trying to do but I just haven't experimented with it enough or read enough about it to feel like I understand how to make the best use of it. Will probably do that soon. Maybe I'm being too neurotic about performance but I anticipate that some of these functions I am writing will be called hundreds of thousands, possibly millions, of times in future computations so I feel like I should do my due diligence now to save as much time on those as I can. – max Apr 27 '23 at 04:16